Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Neue Komponente mit 2 TEdit Komponenten (https://www.delphipraxis.net/134752-neue-komponente-mit-2-tedit-komponenten.html)

Optiplex 28. Mai 2009 08:26


Neue Komponente mit 2 TEdit Komponenten
 
Hallo,
ich muss eine Komponente mit 2 Editfeldern und 6 Feldern mit Textausgabe erstellen. Bevor ich damit beginne wollte ich eure Meinung hören wie man das am besten angeht. Verwende ich TEdit oder besser TCustomEdit? Wie erzeuge ich die Editfelder an besten?Wie bekomme ich die Onchance Ereignise der Editfelder in ein gemeinsames OnChance Ereignis? Wie positioniert man die Editfelder auf seiner Komponente? usw. Ich bin für jeden Hinweis und Erklärung dankbar denn mit solchen zusammengesetzten Komponenten habe ich mich überhaupt noch nicht beschäftigt.

Gruss
Dieter

Bernhard Geyer 28. Mai 2009 08:28

Re: Neue Komponente mit 2 TEdit Komponenten
 
Schau dir doch mal die TFrame-Komponente an.

mkinzler 28. Mai 2009 08:29

Re: Neue Komponente mit 2 TEdit Komponenten
 
TCustom<Kompo> sind die dafür geschaffenen Basisklassen

freak4fun 28. Mai 2009 08:29

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo,
schau mal bei dsdt.info. ;) Hier ist zum Beispiel ein Tutorial. Ich hoffe das hilft dir weiter. :D

Satty67 28. Mai 2009 08:38

Re: Neue Komponente mit 2 TEdit Komponenten
 
Falls schon etwas Basiswissen da ist, ist vielleicht auch der Quellcode von LabeledEdit ganz interessant. Der ist ja bei Delphi mit dabei (zumindest in der kostenlosen Turbo 2006, hoffe dann auch in der 2005 PE?).

Optiplex 28. Mai 2009 11:28

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo zusammen,
danke für eure schnellen Antworten.
Zitat:

Zitat von mkinzler
TCustom<Kompo> sind die dafür geschaffenen Basisklassen

Beim Vorfahrtyp habe ich eigendlich an TCustomControl gedacht, weil dort den Canvas schon integriert ist und so die Textausgaben keine großen Probleme bereiten. Mein Großes Problem sind diese Editfelder wie bekomme ich diese auf die Komponente und kann die Eingaben auswerten(deshalb das OnChanche in das die beiden OnChance Ereignisse der Edits auslösen sollen).
Zitat:

Zitat von Satty67
Falls schon etwas Basiswissen da ist, ist vielleicht auch der Quellcode von LabeledEdit ganz interessant. Der ist ja bei Delphi mit dabei (zumindest in der kostenlosen Turbo 2006, hoffe dann auch in der 2005 PE?).

Nein bei der 2005PE sind keine Quellcodes dabei, würde mir auch nichts nützen da ich keine Komponente kenne die 2 Editfelder besitzt.
Zitat:

Zitat von Bernhard Geyer
Schau dir doch mal die TFrame-Komponente an.

Mir dieser Frame Komponente habe ich bisher überhaupt noch nicht gearbeitet.


Dieter

Satty67 28. Mai 2009 11:57

Re: Neue Komponente mit 2 TEdit Komponenten
 
Zitat:

Zitat von Optiplex
...würde mir auch nichts nützen da ich keine Komponente kenne die 2 Editfelder besitzt.

Ich dachte Du willst Sie doch selber erstellen und nicht eine fertige Komponente? :gruebel: TLabeledEdit hätte ja nur gezeigt, wie man z.B. zwei TEdit's in einer Komponente leicht kombinieren und positionieren könnte. Aber dafür extra TDE2006 installieren um an die Sourcen zu kommen ist natürlich zuviel Aufwand.

TFRame ist einfach, Menü -> Datei -> Neu -> Frame. Ist dann wie ein neues Formular, in das man seine Einzelkomponenten plazieren kann. Das ergebnis ist aber mE. keine neue Komponente, sondern eben ein Frame.

shmia 28. Mai 2009 12:26

Re: Neue Komponente mit 2 TEdit Komponenten
 
Zitat:

Zitat von Optiplex
Bevor ich damit beginne wollte ich eure Meinung hören wie man das am besten angeht.

Man sollte eigentlich nicht mehrere Controls (2 sollte die Obergrenze sein) zu einer neuen Komponente zusammenfassen.
Gründe:
* unflexibel, die Komponente verbirgt das Innenleben meistens so stark, dass man häufig die Schnittstelle der Komponente ändern muss
* umständliche Weitergabe des Projekts - das Installieren der Komponente nervt
* die Komponente lässt sich nur in einem Projekt verwenden, weil sie zu speziell ist
* wenn man öfters solche Spezialkomponenten erstellt, müllt man sich die IDE zu und schleppt den Code im Speicher mit

Wie Bernhard Geyer schon gesagt hat, wäre ein Frame hier das Richtige.
Dabei wichtig: vom Formular aus möglichst nicht direkt auf die Controls auf dem Frame durchgreifen,
sondern über Properties abkapseln.

oki 28. Mai 2009 13:37

Re: Neue Komponente mit 2 TEdit Komponenten
 
Zitat:

Zitat von shmia
Dabei wichtig: vom Formular aus möglichst nicht direkt auf die Controls auf dem Frame durchgreifen,
sondern über Properties abkapseln.

Jetzt muss ich mal dazwischen fragen.

1. Warum nicht durchgreigen?
2. Wenn die Propertys aller enthaltenen Controls abkapseln soll, dann kann er doch auch gleich ein CustomPanel nehmen und daraus eine Komponente mit den enthaltenen Edits usw. schreiben. Das Kapseln macht er dann über einen zentralen Wrapper. Den hat er schön im Inspektor und setzt mit einem Ruck die Eigenschaften aller enthaltenen Controls (z.B. Color, Font etc.).

Gruß oki

shmia 28. Mai 2009 13:59

Re: Neue Komponente mit 2 TEdit Komponenten
 
Zitat:

Zitat von oki
1. Warum nicht durchgreifen?

Damit man innerhalb des Frames die Freiheit hat, etwas zu ändern.
Beispiel:
Das Edit-Control mit Namen EditKanal soll in eine HistoryCombobox (neuer Name CboKanal) umgewandelt werden.
Diese Änderung könnte mehrere Änderungen am Rest der Anwendung nach sich ziehen.
Wenn man dem Frame das Property "Kanal" gibt, dann beschränken sich die Änderungen auf das Frame.
Ausserdem zeigt man so explizit, was in das Frame rein- und rausgeht.

Zitat:

Zitat von oki
2. Wenn die Propertys aller enthaltenen Controls abkapseln soll, dann kann er doch auch gleich ein CustomPanel nehmen und daraus eine Komponente mit den enthaltenen Edits usw. schreiben. Das Kapseln macht er dann über einen zentralen Wrapper. Den hat er schön im Inspektor und setzt mit einem Ruck die Eigenschaften aller enthaltenen Controls (z.B. Color, Font etc.).

Im Prinzip schon.
Aber ein Frame ist leichtgewichtig; man kann schnell mal etwas ändern und darf dann auch man direkt auf die innerliegenden Controls zugreifen.

Eine Komponente ist dagegen schwergewichtig; die innerliegenden Controls sind nicht direkt erreichbar.
Wenn man z.B. die Farbe eines inneren Controls von Aussen ändern möchte, dann muss man ein neues Property einführen.
Dazu muss man das Package neu kompilieren und kann dann erst in der Anwendung das neue Property benützen.
Und dann fällt einem ein, dass das mit der Farbe doch keine so tolle Idee war und man muss den Prozess wieder durchlaufen.
Ich schätze mal, dass eine Änderung an einer Komponente 5 Mal mehr Zeit benötigt, als eine Änderung an einem Frame.

Optiplex 28. Mai 2009 14:19

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo shmia,oki
Natürlich ist das eine Komponente die nur für ein spezielles Projekt ist, und auch nur dort verwendet wird. Die beiden Editfelder sich auch die einzigen Komponenten die auf der Komponente erstellt werden sollen. die Textausgaben werden im Paint der Komponente mit Outtext ausgegeben(deshalb TCostumControl).
Bis jetzt hat mir aber auch noch keiner gesagt wie man zwei Editfelder am besten erstellet, macht man das besser im Constructeur mit self oder nil oder verwendet man eine andere Procedure. Wie führt man die beiden OnChance Ereignisse zusammen in ein Ereignis wie auch immer sie heißen mag. Das sind die Probleme die mich zur Zeit am meisten beschäftigen und auf die ich gerne eine Antwort hätte.
Das mit den Frames ist für mich momentan nur Bömische Dörfer, da ich wie gesagt diese noch nie richtig benutzt habe.Von meiner Komponente benötige ich im eigentlichen Programm bis zu 120Stk geht das mit Frames überhaupt.

Hallo Satty67,
Natürlich vermisse ich die Quelltexte der Komponenten, da man dort doch sehr viel lernen kann.

oki 28. Mai 2009 14:19

Re: Neue Komponente mit 2 TEdit Komponenten
 
@shmia: Überzeugt :mrgreen:

Nur am Rande, ich hasse Frames. Hatte ich nur Ärger mit. Vielleicht hatte ich mich damit auch nur zu blöd angestellt. So ist das halt mit Vorurteilen.

Gruß oki

oki 28. Mai 2009 14:24

Re: Neue Komponente mit 2 TEdit Komponenten
 
grrr roter Kasten!

@optiplex:

Im Constructor mit Owner nil creieren, im CreateWnd Parent self zuweisen (natürlich für die enthaltenen Komponenten).

Das mit den Ereignissen erklär noch mal. Wies geht kann ich dir sagen, aber obs das ist, was du willst?

gruß

shmia 28. Mai 2009 14:30

Re: Neue Komponente mit 2 TEdit Komponenten
 
Zitat:

Zitat von oki
Nur am Rande, ich hasse Frames. Hatte ich nur Ärger mit.

Ähm, ja, das ist mir auch schon aufgefallen.
Niemals Frames ableiten; das funktioniert nicht richtig.
Unterhalb Delphi 5.02 sind Frames ebenfalls sehr zickig.
Und man muss immer mal wieder mit ALT-F12 kontrollieren, welche Properties des Frames in der DFM-Datei des Formulars überschrieben werden und diese ggf. von Hand löschen.
Wenn man das beachtet und es nicht übertreibt mit den Frames, dann kann man damit ganz gut leben.

Optiplex 28. Mai 2009 14:55

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo Oki,
soll das heißen das ich eine Procedure CreateWnd überschreiben muss ? (dann bräuchte ich die genaue Syntax dieser Procedure) um dort die Eigenschaft Parent zuzuweisen. Ich dachte eigentlich dass die Eigenschaften immer im Constructeur zugewiesen werden.

Das mit Edit.Create(nil) im Constructeur habe ich verstanden. Aber warum Nil und nicht Self kannst du mir das erklären?

Das neue Ereignis soll folgendermaßen funktionieren, wird ein Editfeld verändert, soll dadurch das neue Ereignis ausgelöst werden. Ich muss praktische auf Änderungen in den Editfeldern reagieren können.

Ist es besser TEdit oder TCostumEdit zu verwenden?

Dieter

oki 28. Mai 2009 15:57

Re: Neue Komponente mit 2 TEdit Komponenten
 
Delphi-Quellcode:
TMyCustomControl = class(TCustomControl)
privat
  FEdit1 : TEdit;
  FEdit2 : TEdit;
  FOnEditChange : TNotifyEvent;
  ...
protected
  procedure CreateWnd; override;
  procedure EditChangeEvent(Sender : TObject);
published
  property OnEditChange : TNotifyEvent read FOnEditChange write FOnEditChange;
...

procedure TMyCustomControl.CreateWnd;
begin
  Edit1.Parent := self;
  Edit1.OnChange := EditChangeEvent;
  Edit2.Parent := self;
  Edit2.OnChange := EditChangeEvent;
  ...
end;
...
procedure TMyCustomControl.EditChangeEvent(Sender : TObject);
begin
  if Assigned(FOnEditChange) then
    FOnEditChange(Sender);
end;
Der Owner muss nil sein, weil sonst beim Speichern des Formulares in dem du deine neue Kompo verwendest deine Edits mit serialisiert werden (stehen dann in der dfm mit drin). Beim nächsten Laden wird dann ein Edit durch den Construktor erstellt und eins durch die IDE beim Lesen der dfm. Wieder speichern, sind beim nächsten mal schon 3 ....

Verpasse deiner Komponente ein eigenes Ereignis OnEditChange vom Typ TNotifyEvent. Dann so wie oben. Willst du nicht mit dem Sender arbeiten, so kannst du dir da auch eine eigene Ereignisprocedure anlegen und alles was so interessant ist mit hoch reichen.
Bsp.:
Delphi-Quellcode:
  TEditChangeTextEvent = procedure(Sender : TObject; EditText : String) of Object;
Das dann anstelle TNotifyEvent, die Ereignisproceduren anpassen, Text des sendenden Edit mit hochreichen etc.
Oder was immer du oben auch brauchst.

Gruß oki

Optiplex 29. Mai 2009 08:13

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo Oki,
Vielen Dank für die Infos, ich muss also im Constructer die Edit-Felder Createn und in der CreateWnd die Eigenschaften setzen.
Ich gehe davon aus, dass ich die Edit-Felder im Destructor wieder freigeben muss.?
Da du FEdit1 : TEdit; im Code genommen hast nehme ich an,dass du TEdit und nicht TCustomEdit als Vorgänger bevorzugst oder hat dies einen besonderen Grund, dass du TEdit gemommen hast.
Muss ich sonst noch irgendwelche Besonderheiten beachten?
Ich werde am Wochenende mit dieser Komponente beginnen und hoffe, dass ich mit diesen Infos (die sehr gut sind, vor allem weil du sie erklären kannst) diese Komponente erstellen kann ohne allzuviele Fehlermeldungen.

Gruss Dieter,

oki 29. Mai 2009 08:39

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo Optiplex,

ob die Edits von TCustomEdit oder TEdit kommen ist in diesem Fall egal. Du willst sie ja in deiner Komponente verwenden und nicht vererben. Da der Owner nil ist, werden sie ja nicht gestreamt. Somit sind die Published-Felder hier uninteressant.
Bei einer Vererbung eines Edits würde ich TCustomEdit verwenden, hier TEdit.

Und ja, im Destructor frei geben. Das ist besserer Stil. Normalerweise wird beim Beenden der Anwendung automatisch alles frei gegeben, aber sollte deine Componente zur Laufzeit frei gegeben werden, so bleibt eine Speicherleiche. Das automatische Freigeben übernimmt sonst der Owner, der ist hier aber nil.

Sonst noch beachten? Ja, da gibt es einiges, aber im Moment fällt mir konkret nichts bei deinem Ansatz auf. Ich würde mir nur ein ordentliches Handling für dein OnEditChange ausdenken. Da alle Edits das gleiche Ereignis benutzen sollen ist die Identifizierung im Programm recht umständlich, welches Edit nun gerade geändert wurde. Da ich nicht weis, was du vor hast kann ich hier schlecht raten. Auf jeden Fall würde ich nicht TNotifyEvent verwenden sonder eine eigene Ereignisprocedure erstellen. Enthalten sollte die mindestens:
- Sender -> das Panel
- Text -> neuer Text des betroffenen Edits
- EditItent -> Identifier des Edits, das betroffen ist (Name, Index oder sonst was)

Gruß oki

Optiplex 29. Mai 2009 12:01

Re: Neue Komponente mit 2 TEdit Komponenten
 
Danke Oki,
Hier mal ein paar nähere Infos zur Komponente.
Also das ganze gehört zu einem Turnierprogram und in dieser Komponente soll das Ergebnis einer Partie eingetragen werden, im Programm muss ich dann auf diese Eingabe reagieren können, um das Ergebnis auszuwerten(dafür soll das neue Ereignis sein).Die Textausgaben sind nur Texte Spielrunde Startnummern der beiden Spieler und deren Spielernamen sowie der Spielort. Ich habe mich entschlossen eine Komponente dafür zu entwickeln weil bei 16 Spielern in einem Doppel KO system schon 30 Partien notwendig sind und normalerweise wir 32 Spieler bzw 64 Spielern pro Turnier in der Vergangenheit hatten. Dann kannst du dir vorstellen wie viele Edits und Labels notwendig sind um eine Ergebnistabelle zu erstellen und gut aussehen soll das ganze auch noch da der Bildschirm auf eine Leinwand bzw großen LCD-Bildschirm gezeigt wird.
Das ist mein erstes größeres Projekt an den ich bestimmt noch einige Wochen arbeiten werde, da ich nur Hobbyprogrammierer bin, und nur in meiner Freizeit mich damit beschäftigen kann. Deshalb bin ich auch für jede Hilfe oder Tip dankbar.

Gruß
Dieter

oki 29. Mai 2009 12:09

Re: Neue Komponente mit 2 TEdit Komponenten
 
Joop, schönes Projekt.
Überleg dir erst mal, was die Edits melden sollen und was du im Programm von denen als Angaben brauchst um die Eingabe auswerten/verarbeiten zu können. Dann schreib dir dein Ereignis und implementiere das. Solltest du da nicht weiter kommen, helfe ich gerne. Aber erst mal musst du nachdenken. Was du im Programm von den Edits brauchst kann ich schwer sagen.

Gruß oki

oki 29. Mai 2009 12:11

Re: Neue Komponente mit 2 TEdit Komponenten
 
Mir fällt grad ein, brauchst du da nicht ein Panel wo du dynamisch angeben kannst wieviele Paare spielen und dir dann die richtige Anzahl an Edits erstellt?

Gruß oki

Optiplex 29. Mai 2009 13:41

Re: Neue Komponente mit 2 TEdit Komponenten
 
Ja Oki, die Tabelle muss sich dynamisch erweiten von 8,16,32,64 Spielern, das heißt wenn die Spieleranzahl welche mitspielen diese Grenzen erreichen muss die Tabelle entsprechend erweitert werden. wird das Turnier dann gestartet müssen die fehlenden Spielern mit Freilosen aufgefüllt werden, deren Positionen in einem Array gespeichert sind.(damit nicht ein Freilos ins Finale kommt) Ist eine Partie zu ende wird der Gewinner und Verlierer ermittelt (Aufgabe für das neue Ereignis) und die Spieler werden dann entsprechend in der Tabelle einer neuen Partie zugeordnet ist eine Partie vollständig dann kann diese gespielt werden. usw.
Schön dass du mir deine Hilfe anbietest werde ich auch bestimmt nutzen und gebrauchen können.
Es kann allerdings sein, dass ich mich erst wieder nächsten Dientag melden kann, ich hoffe dass ich bis dahin recht weit bei meinem Komponentenbau gekommen bin.

Bis dann Dieter

oki 29. Mai 2009 14:35

Re: Neue Komponente mit 2 TEdit Komponenten
 
Joop, wenn du Fragen hast, her damit. Ich bin aber auch erst am Mittwoch wieder da, und da wo ich bis dahin bin, gibs kein INet. :cry:

Gruß oki

Optiplex 2. Jun 2009 08:08

Re: Neue Komponente mit 2 TEdit Komponenten
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo oki,
dank deiner Hilfe habe ich die Komponente TDartResultEdit am WE entwickelt. Siehe Anhang ( TDartResultEdit.Jpg ), was noch nicht implementiert ist das OnEdirChance Ereignis. Hier muss ich mir noch genau überlegen wie ich dieses Ereignis mache. Ich habe am WE viel dazugelernt aber es haben sich auch viele Fragen ergeben die du mir vielleicht beantworten kannst

Leider musste ich feststellen, dass der Focus zum Aktiven Control auf meiner Komponente wandert. Kann man das Irgendwie verhindern in dem das Control zwar aktiviert wird aber der Focus bei meiner Komponenete bleibt. Dadurch musste ich, weil ich eine Cursorsteuerung implementiert hatte, diese Auf die OnKeyDown Ereignisse des jeweiligen Controls umleiten dies hatte zur folge das die Cursorsteuerung nicht mehr so richtig funktionierte( Vor alle bei einem TButtom). Mit
Delphi-Quellcode:
Protected
procedure WMGetDLGCode(var msg: TMessage); message WM_GETDLGCODE;
....
Procedure TDartResultEdit.WMGetDLGCode(var msg: TMessage);
begin
  inherited;
  msg.Result:= msg.Result or DLGC_WantArrows;
end;
kann man bei seiner Komponente die CursorTasten abfangen. Wie macht man das bei den SubKomponenten? Dies ist das Aktuelle OnKeyDown Ereignis das wie gesagt an den Subkomponenten hängt(Sorry hatte noch keine Zeit den Code zu bereinigen)
Delphi-Quellcode:
procedure TDartResultEdit.EditKeyDownEvent(Sender: TObject; var Key: Word; Shift: TShiftState);
var iii:integer;
  obj: tObject;
  edi:TEdit;
  btn:TButton;
begin
  obj:=nil;
  If(Key=vk_Down) or (Key=vk_up)then begin
    for iii :=0 to Parent.ComponentCount-1 do
      if Parent.Components[iii].classtype=TDartResultEdit then begin
        if TDartResultEdit(Parent.Components[iii]).enabled and
          TDartResultEdit(Parent.Components[iii]).Visible then
          case Key of
            vk_Down:
              begin
                if (TDartResultEdit(Parent.Components[iii]).Left = Left) and
                  (TDartResultEdit(Parent.Components[iii]).Top > Top)then
                  if obj=nil then obj:= Parent.Components[iii]
                else
                  if (TDartResultEdit(Parent.Components[iii]).Top < TDartResultEdit(obj).Top)
                    then obj:=Parent.Components[iii];
              end;
            vk_up:
              begin
                if (TDartResultEdit(Parent.Components[iii]).Left = Left) and
                  (TDartResultEdit(Parent.Components[iii]).Top < Top)then
                  if obj=nil then obj:= Parent.Components[iii]
                else
                  if (TDartResultEdit(Parent.Components[iii]).Top > TDartResultEdit(obj).Top)
                    then obj:=Parent.Components[iii];
              end;

          end;
      end;
      if obj<>nil then
        if TDartResultEdit(obj).Enabled and TDartResultEdit(obj).Visible then TDartResultEdit(obj).Setfocus;
  end;
  if Key=vk_Right then begin
    if Sender.ClassType =TEdit then begin
      edi:=TEdit(Sender);
      if edi.Name = FPlayerEdit1.Name then FPlayerEdit2.SetFocus;
//      if edi.Name = FPlayerEdit2.Name then FBoardButton.SetFocus;
    end;
//    if Sender.ClassType =TButton then FPlayerEdit1.SetFocus;
  end;
//      btn:=TButton(Sender);
//      if edi.Name = FPlayerEdit1.Name then FPlayerEdit2.SetFocus;
//      if edi.Name = FPlayerEdit2.Name then FBoardButton.SetFocus;
//    end;
  if Key=vk_Left then begin
    if Sender.ClassType =TEdit then begin
      edi:=TEdit(Sender);
      if edi.Name = FPlayerEdit2.Name then FPlayerEdit1.SetFocus;
//      if edi.Name = FPlayerEdit1.Name then FBoardButton.SetFocus;
    end else FPlayerEdit2.SetFocus;
//    if Sender.ClassType =TButton then FPlayerEdit2.SetFocus;
  end;
//  if Key=VK_Space then Click;
  inherited;
end;
Funktioniert mit den TEdits . Ich wollte noch einen Button (Auswahl Spielort) rechts am Ende der Komponenete integrieren,(was mit deiner Beschreibung kein Problem war, auch ein eigenes Ereignis war schnell integiert),doch leider bringt dieser Button meine Cursorsteuerung durcheinandert, bei hoch und runter springt er nicht zur nächsten Komponente innerhalb der TDartResultEdit Klasse(was bei den Edits einwandfrei funktioniert) sondern auf das erste bzw. zweite Editfeld innerhalb der Subkomponenten. (Warum?).

Kann man den Text ein einem Editfeld zentrieren?

So und nun noch mal zu OnEditChance.
Die Eingabe der Edits habe ich auf Zahlen beschränkt(funktioniert). Ich muss in diesem Ereignis
1.Die Gültigkeit des eingegebenen Ergebnisses auswerten (best of)
2 Ist das Spiel durch dieses Ergebnis beendet oder läuft es noch weiter
3.Ist es ein Endergebnis (best of) dann Verlierer und Gewinner auswerten und diese in die nächste Runde springen bzw. ausscheiden lassen.

Dazu brauche ich alle TEdit.Texte und natürlich den Sender da das im meinem Programm eigentlich nur eine Routine werden soll. Was meinst du wie ich das hier am besten löse?
Du hast mir ja schon zwei eventuelle Lösungen genannt welche soll ich bevorzugen?

Da du für das Projekt Intresse hast, habe ich dir ein PrintScreen von einem Spielplan (Ist aber auch noch nicht 100% fertig) so wie er Später im LCD-Fernseher oder Leinwand zu sehen sein wird angehängt. Über die Komponente TDartResultEdit werden die Ergebnisse und die daraus folgenden Partien in diesen Spielplan eingetragen.

Sind genug Fragen auf einmal (hoffe ich werde dir nicht lästig).

Gruß Dieter

Natürlich kann sich jeder hier beteiligen der eine Lösung für meine Fragen kennt

Optiplex 4. Jun 2009 11:38

Re: Neue Komponente mit 2 TEdit Komponenten
 
Huch hab ich euch jetzt erschreckt?

Dieter

oki 4. Jun 2009 14:19

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo,

ja, eine ganze Menge Fragen, erschreckt aber nicht. Bin seit heute erst wieder zurück.
Ich denke, wir machen eins nach dem anderen. Das ganze Thema mit dem Fokus habe ich noch nicht so richtig geschnallt. Ich würd lieber mit den Ereignissen anfangen.
Du hast ja eine recht eindeutige Nummerierung deiner Spiele. Ich denke mal, dass du im Programmablauf auf die Eigaben bezüglich der Auswertung usw. reagieren willst. Wobei ich denke, dass das auch in der Kompo klappen sollte.
Ich würde der Kompo erst ein mal eine Property PlayerCount verpassen. Da gibt man dann die Anzahl der Spieler ein. Daraus wird dann auch automatisch das Schema in deiner Abbildung Spielplan_16 erstellt. Die Anzahl der TDartResultEdits ergibt sich ja automatisch. Jedes Edit sollte als Name den Text erhalten, den du über die Spielerpaare geschrieben hast mit dem suffix 1 oder 2 erhalten.
Bsp.:
Delphi-Quellcode:
  For PlayRount := 1 to PlayerCount div 2 do begin
    For Player := 1 to 2 do begin
      with TDartResultEdit.create(nil) do begin
        Name := Format('R1_%d_%d', [PlayRound, Player]);
        OnChange := self.OnDartResultEditChange;
        ...
Das ist nur ein erster Ansatz. Die Logik, wieviel Spiele wie zusammengestellt werden kennst du selbst am besten.
Jetzt nimmst du dein Ereignis On Change und wertest die Einträge aus. Somit kannst du gleich alle folgenden Felder mit den Spielernamen füllen.
Delphi-Quellcode:
procedure MyCustomControl.OnDartResultEditChange(Sender : TObject);
var SenderName : String;
    RoundChar : Char;
    PLayRound, Player : Integer;
begin
  // hier macht es Sinn, den Namen des sendenden Edit zu zerlegen.
  if not Sender is TDartResultEdit then
    Exit;
  SenderName := TComponent.Name;
  // jetzt zerlegen und auf die einzelnen Segmente prüfen
  case ORD(RoundChar) of // das ist z.B. das R
    ORD('R') : begin
      case PlayRound of // das ist das Spiel der Runde
        1 : begin
            .... // usw.
        end;
      end;
    end;
    ...
  end;
end;
Ich denke, dass es Sinn macht, die einzelnen Cases in Funktionen auszulagern. Desgleichen würde ich für die einzelnen Spieler eine eigene Klasse TPlayer = class TObject anlegen. Die dann alle in einer ObjectList halten. So wird die Verwaltung einfacher. An das Programm würde ich eigentlich nichts hoch senden. Die Einträge in die weiteren Felder kann eigentlich deine Komponente machen. Über das Programm steuerst du eigentlich nur den Input wie Anzahl Spieler, Spielername, zufällige oder feste Paarbildung usw.

Ich glaube, ich hab hier versehentlich TDartResultEdit als Eingabefeldt (Edit) des Spielstandes gesetzt. Wenn das falsch ist, sag bescheid.

Jo, sag mal, wie dier das gefällt. Dann können wir ja konkret weiter machen.

Gruß oki

Optiplex 4. Jun 2009 15:07

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo Oki,

wie ich sehe hast du dir den Spielplan genau angesehen, nun noch ein paar Erklärungen dazu. also R1-1 bis R1-8 bedeutet Runde 1 Spiel 1-8 da dies ein Doppel OK System ist gibt es eine Gewinnerseite G und eine Verliererseite V daraus ergibt sich die Gewinnerrunde1 Spiel 1-4 und eine Verlierer Runde 1 Spiel1-4 usw. Verliert ein Spieler ein zweites mal scheidet er aus, verliert ein Spieler in der Gewinnerrunde kommt er in die Verliererrunde und zwar an die Sprungpunkte A-G je nachdem wie weit er in der Gewinnerrunde gekommen ist.
ich wollte bei unserer Komponente noch zweit Eigenschaften hinzufügen und zwar einmal Gewinner und Verlierer als String und hier sollten die Runde eingetragen werden bei der es weitergeht( zB G1-2/2 oder V1-2/1) die /1 bzw. /2 bedeutet, Spieler1 bzw. Spieler2 in unser Komponte. Hinterlegt wird in der entsprechenden Runde G1-2 usw. Damit könnte ich den kompletten Ablauf des Turniers mit der Ergebnistabelle steuern.

(Natürlich könnte man auch einen Array erstellen, aber darüber habe ich noch nicht nachgedacht wie der Aussehen müsste.)

So hatte ich mir das ungefähr Theoretisch vorgestellt.

Allzu weit weg sind deine Gedanken über den Ablauf ja nicht von den meinen und ich werde mir heute Abend darüber nachdenken ob deine Idee nicht besser ist, mit der Auswertung innerhalb der Komponente, wobei die Auswertung recht komplex ist.

bis dann Dieter

Optiplex 5. Jun 2009 08:10

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo Oki,
also gegen eine Auswertung in der Komponente ist nichts einzuwenden, allerdings bräuchten wir hier noch ein Property BestOf damit die Eingabe ausgewertet werden kann (best of 3,5,7,9,11), dann muss noch ein Property Gewinner/Verlierer(Startnummer/Name des Spielers) dazu damit diese an die nächste Runde weitergegeben werden kann. Wie du sicherlich gemerkt hast ist jede Runde mit einer weiteren Runde Verlierer/Gewinner fest verknüpft und diese Verknüpfung wollte ich fest in die Komponente den Propertys Verlierrunde/Gewinnerrunde(siehe gestern) mit angeben. Diese beiden Propertys sind eigentlich nur Dummys und werden von unserer Komponente nicht beeinflust. So habe ich alle wichtigen Infos an die Komponente gelegt. Die weiteren Eintragungen in der Ergebnistabelle und im Spielplan würde ich dem eigentlichen Programm überlassen.(man braucht nur die Captions zu vergleichen und die Propertys auszutauschen) Die Anzahl der Spieler ist immer gleich bei einem Doppel OK System (entweder 8,16,32,64,128) fehlende Spieler werden durch Freilose deren Position in Runde 1 fest vorgegeben sind (damit nicht ein Freilos in die Ränge kommen kann ).Der benötigte Spielplan wird dann über die angemeldeten Spieler ausgewählt.

Ich werde dir am WE einmal zusammenschreiben wie so ein Turnier abläuft und auf was zu achten ist damit du auch die Infos alle hast.(Hoffentlich vertreibe ich dich damit nicht, weil so ein Event doch ziehmlich Komplex ist).

oki 5. Jun 2009 08:45

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo,
ich sehe das mit der Auswertung nicht so problematisch. Sobald ein Ergebnis in eingegeben wird ist ja klar, wer gewonnen hat. Somit ist auch gleich eindeutig, in welchem Feld (G, V usw.) der entsprechende Spieler eingetragen wird. Auch die Numerik für das entsprechende Spiel ist logisch nachvollziehbar, unabhängig von der Anzahl der Spieller und Runden. So gehen z.B. die Gewinner der Runde R1-1 und R1-2 in die Runde G1-1, aus R1-3 und R1-4 in G1-2 usw. Das ist imho wieder eine 2 zu 1 Beziehung in einer weiteren Ebene. Diese Gewinner gehen in G2-1 auf(Gewinner aus G1-1 und G1-2 nach G2-1). Wieder eine 2 zu 1 Beziehung. Der Vorteil ist sogar, dass somit ein relativ einfaches mathematisches Prinzip abgebildet werden kann. Und das gilt dann eigentlich sehr universell. Aus zwei mach eins eine Ebenen höher. Rieht ganz deutlich nach einer universellen Funktion mit einem simplen Vergleich und Inkrementieren der Spielebene.

Wenn man das im Griff hat, kann man die Ermittlung des neuen Eintragfeldes für einen Spieler recht universell über eine Funktion ermitteln, bei der man die Aktuelle Runde, beide Spielpartner und den Spielstand übergiblt. Zurück bekommt man die Bezeichner der Felder, in die die Spieler neu einzutragen sind.

Für die Übersicht des aktuellen Standes würde ich über die Spieler und die Spielerliste gehen. Dazu würde ich noch eine zusätzliche Liste der Spiele anlegen. Das in etwa so:
Delphi-Quellcode:
  TPlayResult : TPoint; // TPoint zweckentfremden für Spielstand oder gleich eigener Typ
  // Vorward-Declaration
  TPlayerClass : class;

  TPlayClass = class(TObject)
  private
    FPlayResult : TPlayResult;
    FPlayer1: TPlayerClass;
    FPlayer2: TPlayerClass;
    FRound : String;
  ....
  end;
 
  // Liste der durchgeführten Spiele jedes Spielers
  TPlayList = class(TObjectList)
  ...
  end;

  TPlayerClass = class(TObject);
  private
    FParentList : TPlayList;
    FPlayerName : String;
    ....
    FPlayList : TPlayList;
    FPosition : Integer; // aktueller Platz des Spielers im Turnier
    ...
  end;

  // Liste aller Spieler
  TPlayerList = class(TObjectList)
  private
    FParentControl : TMyControl;
  ....
  end;
Jetzt hast du folgende Möglichkeiten. Deine neues Control hat die Eigenschaften PlayerList. Wird PlayerList verändert, so kann dein Control aus dem Member Count der PlayerList den Spielaufbau generieren. Alle weiteren Eigenschaften wie zufällige Spielpaarzusammenstellung usw. lassen wir mal außer acht. Das ist Finetuning und berührt die generelle Funktion der Komponente nicht.
Über das Programm kannst du die Bearbeitung der PlayerListe incl. des einzelnen Players steuern. Ähnlich, als ob du mit einer Datenbank arbeitest. Durch die Zuweisung, Änderung reagiert deine Komponente. Willst du das automatisieren, so erhält deine PlayerList noch einen Member ParentControl. Der kann dann vom Typ deiner Komponente sein. Ist dieser Member ungleich nil, so informiert die PlayerListe automatisch das ParentControl über Änderungen, damit diese sich in der Ansicht aktualisieren kann. Das gleiche kannst du natürlich auch mit der PlayerClass machen. Der Witz währe folgender.
Mitten im Spiel bemerkt ein Spieler, dass seine Name Falsch eingetragen ist. Du änderst über die Eingabemaske den Namen in seinem zugehörigen Klassenobjekt TPlayerClass. Der Setter für den Namen ruft eine eigene Methode ChangePlayer der PlayerList auf, die ja als Member in TParentList abgelegt ist. Diese wiederum ruft die eigene Methode Change der ParentComponent auf. Die Parent Component zeichnet sich damit neu. Dabei macht es dann Sinn, wenn die Edits zusätzlich einen Member der Player haben, denen das entprechende Player-Object zugewiesen wurde. Du trägst also nicht den Namen des Spielers ein, sondern weist einen zu. Der Name wird beim zeichnen also aus der Eigenschaft PlayerName des PlayerObjectes eingetragen. Durch die Methode Change wird ja die Componente neu gezeichnet. Der Name in PlayerName des Edits hat sich in der Zwischenzeit geändert und somit neu gezeichnet.
Alles automatisch, keiner rekursiven Funktionen nötig, ändern an der Stelle wo man ändern muss, neu zeichnen und alles fertig und up to date. Großer Zauber Manitu.

Hast du in den Edits die neuen Spielstände eingetragen, so wird über die EditChange-Methode die oben beschriebene Auswertefunktion angestoßen. Ein Object der TPlayClass wird erstellt, dem Player zugewiesen, den neuen Eintragsfeldern (Edits) das richtige Playerobject zugewiesen, refresh (Change deiner Komponente) fertig.

Aktuelle Listen für Spielstand, Platz jedes Spielers usw. implementierst du als Funktionen deiner PlayerList, die du über das Hauptprogramm aufrufst und das entsprechende Ergebnis von der Funktion zurück bekommst.

Im Prinzip passiert hier folgendes. Du hast:
- Datenklassen wie TPlayClass, TPlayList (Spiel, Spielliste), TPlayerClass, TPlayerList (Spieler, Spielerliste).
- Visualisierungsklassen -> deine Komponente
- Ein-/Ausgabeklassen; deine Komponente für Spielstände, Eingabemaske für die Spieler
- GUI; Hauptprogramm, auf dem die visuellen Komponenten platziert sowie die Menüs und Buttons für die Spielsteuerung und Einstellungen platziert sind.

Joo, so würde ich es in etwa machen. Das Thema mit den PlayClass ist mir noch nicht ganz sauber. Finde im Moment aber keinen Ansatz das zu vereinfachen oder zu zentralisieren. Ich habe den Eindruck, man muss das über die PlayList aufziehen und denen die Player zuweisen und nicht umgekehrt. Kann man ja noch drüber nachdenken. Aber ich glaube so ist es richtig.

Gruß oki

oki 5. Jun 2009 08:50

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hatte wohl etwas lange an dem letzten Beitrag geschrieben.

Hallo optiplex :lol:
sorry für die Monologe. Ich empfehle folgendes. Wir erstellen erst die Datenmodelle. Dann die visuellen Komponenten. Das mit den Funktionen und Eigenschaften ist dann ganz einfach. Die können sucsessive erweitert werden. Wenn die Struktur und die Klassen stimmen ist das andere alles ein Klacks. Vertrau mir, ich wies was ich tu ( :mrgreen: kennst du den Spruch? stammt aus einer alten Serie)

gruß oki

oki 5. Jun 2009 10:41

Re: Neue Komponente mit 2 TEdit Komponenten
 
Also, ich hab noch mal nachgedacht. Du solltest die PlayList nicht den Playern zuordnen, sondern die Player den PlayClasses. Das macht mehr Sinn.

Wenn du Hilfe bei der Erstellung der Klassen brauchst sag bescheid, dann mach ich das (brauch mal ne kleine Ablenkung mit ner leichten Aufgabe).

Gruß oki

Optiplex 5. Jun 2009 12:12

Re: Neue Komponente mit 2 TEdit Komponenten
 
Puuu Oki, das ist harte Kost für mich.
Mit Klassen habe ich mich noch nicht so viel beschäftigt und kenne deren Vor- und Nachteile überhaupt nicht. Ich habe auch noch nicht geschnallt, wie du das mit den Verknüpfungen, wann und wo welcher spieler weiterspielt oder ausscheidet über die Klassen regeln willst. Das mit einer kompletten Teilnehmerliste ist OK die hätte ich sowieso gebraucht auch schon wegen der eventuellen Namensänderung.

Du schreibst das so als wäre das alles kein Problem. Für mich sind da ein paar böhmische Dörfer schon dabei, werde allerding versuchen mich am Wochenende schlau zu machen, und wie gesagt fehlen dir noch ein paar Infos die ich am Wochenende zusammenschreiben werde, nur damit du nicht unnötig zeit investierst und sagst das hättest du mir gleich sagen sollen.

Datenmodel erstellen ? wie ? aber ich bin lernbereit, denn wie gesagt ich bin Hobbyprogrammierer.

Leider habe ich am Wochenende kein Inet, es kann daher sein, dass ich mich erst am Montag wieder melde.(bin aber heute bis 16 Uhr erreichbar und schaue nochmal hier vorbei.

Zitat:

Zitat von oki
Vertrau mir, ich wies was ich tu( :mrgreen: kennst du den Spruch? stammt aus einer alten Serie)

Den Spruch kenne ich, weis nur die Serie nicht mehr.

Gruss Dieter

oki 5. Jun 2009 12:37

Re: Neue Komponente mit 2 TEdit Komponenten
 
Slatch Hammer (ob richtig geschrieben, keine Ahnung?), das war der Bulle, der in seine Knarre verliebt war und ständig mit der rumgeballert hat (z.B. Fliegen von der Wand :mrgreen: ).
das zum wichtigen Teil der der Nachricht. :mrgreen:

So, nun zum Datenmodell. das ist gar nicht so schwer. Fangen wir mal ganz vorne an; die Player.

Hier mal auf die Schnelle die Klassen für die Spieler und die Spielerliste. Alle Funktionen für die Statistiken usw. die direkt die Spieler betreffen generieren wir dann in der PlayerList.

Delphi-Quellcode:
unit Player_Classes;

interface

type
  // Forward
  TPlayerList = class;

  // Der ShowMode definiert, wie der Name des Spielers ausgegeben wird
  TShowNameMode = (snm_FullName,         // Vorname und Name anzeigen
                   snm_Name,               // nur Nachname anzeigen
                   snm_ShortFirstName // Vorname abgekürzt, Nachname voll
                   );

 (*
   Klasse eines einzelnen Spielers. Der Member PlayerList gibt die übergeordnete Liste
   an, die den Spieler hält.
 *)
  TPlayerClass = class(TObject)
  private
    FBirthday: TDateTime;
    FFirstName: String;
    FName: String;
    FPlayerList: TPlayerList;
    FShowNameMode: TShowNameMode;
    function GetFullName: String;
    procedure SetBirthday(const Value: TDateTime);
    procedure SetFirstName(const Value: String);
    procedure SetName(const Value: String);
    procedure SetShowNameMode(const Value: TShowNameMode);
  public
    property PlayerList : TPlayerList read FPlayerList write FPlayerList;

    property Birthday : TDateTime read FBirthday write SetBirthday;
    property FirstName : String read FFirstName write SetFirstName;
    property Name : String read FName write SetName;
    property ShowNameMode : TShowNameMode read FShowNameMode write SetShowNameMode;

    property FullName : String read GetFullName;
  end;

  TPlayerList = class(TObjectList)
  private
  protected
     function GetItem(Index: Integer): TPlayerClass;
     procedure SetItem(Index: Integer; AObject: TPlayerClass);
  public
     function Add(AObject: TPlayerClass): Integer;
     function Extract(Item: TPlayerClass): TPlayerClass;
     function Remove(AObject: TPlayerClass): Integer;
     function IndexOf(AObject: TPlayerClass): Integer;
     procedure Insert(Index: Integer; AObject: TPlayerClass);
     function First: TPlayerClass;
     function Last: TPlayerClass;

    procedure PlayerChanged;

     property Items[Index: Integer]: TPlayerClass read GetItem write SetItem; default;
  end;

implementation

{ TPlayerClass }

function TPlayerClass.GetFullName: String;
begin
  case FShowNameMode of
    snm_FullName: Result := Format('%s %s', [FFirstName, FName]);
    snm_Name: Result := FName;
    snm_ShortFirstName: Result := Format('%s. %s', [FFirstName[1], FName]);
  end;
end;

procedure TPlayerClass.SetBirthday(const Value: TDateTime);
begin
  if FBirthday = Value then
    Exit;
  FBirthday := Value;
  if Assigned(FPlayerList) then
    FPlayerList.PlayerChanged;
end;

procedure TPlayerClass.SetFirstName(const Value: String);
begin
  if FFirstName = Value then
    Exit;
  FFirstName := Value;
  if Assigned(FPlayerList) then
    FPlayerList.PlayerChanged;
end;

procedure TPlayerClass.SetName(const Value: String);
begin
  if FName = Value then
    Exit;
  FName := Value;
  if Assigned(FPlayerList) then
    FPlayerList.PlayerChanged;
end;

procedure TPlayerClass.SetShowNameMode(const Value: TShowNameMode);
begin
  if FShowNameMode = Value then
    Exit;
  FShowNameMode := Value;
  if Assigned(FPlayerList) then
    FPlayerList.PlayerChanged;
end;

{ TPlayerList }

function TPlayerList.Add(AObject: TPlayerClass): Integer;
begin
  AObject.FPlayerList := self;
  Result := inherited Add(AObject);
end;

function TPlayerList.Extract(Item: TPlayerClass): TPlayerClass;
begin
  Result := TPlayerClass(inherited Extract(Item));
  result.FPlayerList := nil;
end;

function TPlayerList.First: TPlayerClass;
begin
  Result := TPlayerClass(inherited First);
end;

function TPlayerList.GetItem(Index: Integer): TPlayerClass;
begin
  Result := TPlayerClass(inherited GetItem(Index));
end;

function TPlayerList.IndexOf(AObject: TPlayerClass): Integer;
begin
  Result := inherited IndexOf(AObject);
end;

procedure TPlayerList.Insert(Index: Integer; AObject: TPlayerClass);
begin
  AObject.FPlayerList := self;
  inherited Insert(Index, AObject);
end;

function TPlayerList.Last: TPlayerClass;
begin
  Result := TPlayerClass(inherited Last);
end;

{-----------------------------------------------------------------------------
  Procedure:  PlayerChanged
  Author:     Dipl. Ing. Olaf Keitsch
  Date:       05-Jun-2009
  Arguments:  None
  Result:     None
  Describtion: Diese Methode wird von den Settern der Player aufgerufen. An dieser
               Stelle kann die Aktualisierung des anzeigenden Controls aufgerufen werden.
-----------------------------------------------------------------------------}
procedure TPlayerList.PlayerChanged;
begin
  // do it
end;

function TPlayerList.Remove(AObject: TPlayerClass): Integer;
begin
  AObject.FPlayerList := nil;
  Result := inherited Remove(AObject);
end;

procedure TPlayerList.SetItem(Index: Integer; AObject: TPlayerClass);
begin
  AObject.FPlayerList := self;
  inherited SetItem(Index, AObject);
end;

end.
Alles, was die Spiele betrifft kommt dann in die PlayList. Das später.
In der Klasse PlayerList kannst du jetzt in den Propertys noch ergänzen, was du direkt zu den Spielern an Angaben erfassen willst. Hier kommt aber nichts zu den Spielen rein.

Gruß oki

Optiplex 5. Jun 2009 14:33

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo Oki,
Mensch du bist schneller als die Polizei erlaubt, hast du das alles fertig in der Schublade? Hab dir schnell mal zusammengeschrieben, damit du alle Infos hast die du brauchst.

Da ein Dart Event aus mehreren Turnieren (Einzel Doppel in den jeweiligen Klassen) besteht die meist gleichzeitig laufen, habe ich mich entschlossen einen Eventmanager (Eigenständiges Programm) zu programmieren

Im Manager sollen alle wichtigen eingaben die alle Turniere Betreffen erfolgen

-Eingabe der Anzahl der vorhandenen Automaten
-Sperrung eines Automaten
-Eingabe der Spieler zum jeweiligen Turnier
-starten eines Turniers (eigenständiges Programm je nach Anzahl der Spieler hier sind wir gerade mit unserer Komponente.)
-unterbrechen eines Turniers
-Turnier wieder aufnehmen.
-ein Spieler gibt auf weil er dringend weg muss dann soll der Spieler an allen Turnieren an denen er angemeldet ist praktisch als Freilos weitergeführt werden, bis das Freilos ausgeschieden ist.

Alles was alle Turniere betrifft wird in einer zentralen Datei gespeichert. hier rufen die einzelnen Turniere ihre Daten ab oder schreiben hinein. Ist wichtig bei Stromausfall, damit der Event an diesem Punkt weitergeführt werden kann. (sonst kann es passieren dass eine Horde über mich herfällt)

Ablauf Erstellung eines Events

Eingabe der Anzahl der vorhandenen Automaten
Eingabe des Event namens = Dateiname der Ini
Speicherung des Events in einem Verzeichnis. Anlegen einer INI - Datei mit den Grundeinstellungen

Belegung der Automaten (Überwachung)
jeder Automat an dem gespielt wird muss als belegt gekennzeichnet werden, damit er zur Auswahl in den Turnieren nicht mehr zur Verfügung steht.

Automatenausfall
Es muss möglich sein einen Automaten zu sperren (defekt) wird gerade dort gespielt muss eine Info zur Partie gehen, damit dort ein neuer Automat ausgewählt werden kann.

Freilose(Überwachung)
ist eine Partie mit einem Freilos komplett so wird sofort das Freilos als Verlierer gewertet und wird dementsprechend weitergereicht bzw. scheitet aus dem Turnier aus.

Spieler spielt bereits in einem anderen Turnier (Überwachung)
Jeder Spieler der gerade eine Partie spielt muss gekennzeichnet werden, damit er nicht nochmals zu einer Partie aufgerufen werden kann.

Ein Spieler beendet vorzeitig das Turnier.
gibt ein Spieler das Turnier vorzeitig auf so wird er ab dieser Runde behandelt wie ein Freilos.

So nun hast du denke ich alle Infos die du brauchst. Ich hab dir ja gesagt dass das ganze ziemlich komplex ist. (Hoffentlich habe ich dich jetzt nicht verjagt)
Wenn du willst kannst du dir ja ein Paar Gedanken machen.

Ich werde mich mal mit deinen Klassen beschäftigen, scheint auf den zweiten Blick die Lösung für einige Probleme zu sein, bin aber noch nicht ganz durchgestiegen.

Richtig ! An die Serie kann ich mich noch erinnern.

Gruss bis Montag Dieter.

oki 5. Jun 2009 15:32

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo Dieter,

Dank für deine Erläuterungen. Bin zwar noch nicht ganz durchgestiegen bei den Themen Automaten, Events usw., fehlt mir die Praxis. Trotzdem sehe ich das alles nicht so wild. Entscheidend ist hier einfach nur der intelligente Klassenaufbau für die Spiele. Da hab ich das Thema Turniere usw. noch nicht ganz geschnallt. Vorallem die Abhängikeiten usw. Das ignoriere ich jetzt aber mal geflissentlich. Hat in der Ebene in der wir gerade stecken wohl noch keine Auswirkungen. Ich versuche gerade herauszubekommen, was wir alles für die PlayClass an Eigenschafen brauchen. Auf deutsch, was ist alles für ein Spiel (Paar) an Informationen relevant. Die beiden Spieler ist sicher klar. Dann der Spielstand. Was gehört noch alles zu einem Spiel? Der Automat vielleicht? Da musst du mal paar Angaben machen. Die PlayList hält dann zwar die einzelnen Spiele eines Turniers (denke ich), muss dann aber sicher noch einige Funktionen haben. Da musst du wieder helfen.
Ich hatte mir das Händling dafür so vorgestellt. Die PlayList hält die PlayClass'es. wird in einer PlayClass ein Spielstand gespeichert, so wird die Playlist davon informiert (so wie das mit den Änderungen bei den Playern). Dabei wird dann aber das PlayObject mitgeliefert (Methode ChangePlayClass der PlayList). Das die PlayList dann weis, in welchem Spiel sich der Spielstand wie geändert hat, kann sie automatisch ermitteln, in welche weiteren Play-Objekte seiner Liste die entsprechenden Spieler eingetragen werden müssen. Ein Status für das entsprechende Spiel zum Sperren usw. kann dann die Playlist mit vergeben. Dazu kann man der PlayClass eine entsprechende Eigenschaft verpassen. Das alles ist schon mit Sicht auf die spätere Anzeige gedacht. Da machen sich solche Statusflags immer toll um die Anzeige anzupassen.

Naja, ich denk mir da mal was aus.

bis die Tage,

Gruß oki

oki 7. Jun 2009 10:03

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hi,

ich hab mal die Klassen für die Spieler, Spielerliste, Spiele und Spielliste fertig gestellt. Leider hab ich das System für den Eintrag eines Spielers in ein neues Spiel noch nicht ganz durchschaut. Für die Gewinner ist das ja recht einfach. Bei den Verlierern hab ich da so meine Probleme. Ich pack hier mal die Procedure rein.
Delphi-Quellcode:
procedure TPlayList.ChangePlay(APlayClass: TPlayClass; AProperty : String);
var AWinner, ALooser : TPlayerClass;

  procedure PlayerinGame(APlayer : TPlayerClass; AOldPlay : TPlayClass; winning : Boolean);
  var NewPlay : TPlayClass;
  begin
    if winning then begin
      // Spieler ist Gewinner des alten Spieles
      case ORD(AOldPlay.FGame) of
        ORD('R') : begin
          // Gewinner der ersten Runde
          if Odd(AOldPlay.Number) then begin
            NewPlay := GetPlay('G', 1, (AOldPlay.Number+1) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer1 := APlayer;
          end else begin
            NewPlay := GetPlay('G', 1, (AOldPlay.Number) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer2 := APlayer;
          end;
        end;
        ORD('G') : begin
          if Odd(AOldPlay.Number) then begin
            NewPlay := GetPlay('G', AOldPlay.FRound+1, (AOldPlay.FNumber+1) div 2);
            if Assigned(NewPlay) then begin
              NewPlay.FPlayer1 := APlayer;
            end else begin
              // das war das letzte Gewinnerspiel, ab ins Filale
              NewPlay := GetPlay('F', 0, 0);
              if Assigned(NewPlay) then
                NewPlay.Player1 := APlayer;
            end;
          end else begin
            NewPlay := GetPlay('G', AOldPlay.FRound+1, (AOldPlay.FNumber) div 2);
            if Assigned(NewPlay) then begin
              NewPlay.FPlayer2 := APlayer;
            end else begin
              // das war das letzte Gewinnerspiel, ab ins Filale
              NewPlay := GetPlay('F', 0, 0);
              if Assigned(NewPlay) then
                NewPlay.Player1 := APlayer;
            end;
          end;
        end;
        ORD('V') : begin
          NewPlay := GetPlay('V', AOldPlay.Round + 1, 1);
            if Assigned(NewPlay) then begin
              NewPlay.FPlayer1 := APlayer;
            end else begin
              // das war das letzte Gewinnerspiel, ab ins Filale
              NewPlay := GetPlay('F', 0, 0);
              if Assigned(NewPlay) then
                NewPlay.Player2 := APlayer;
            end;
        end;
      end;
    end else begin
      // Spieler ist Verlierer des alten Spieles
      case ORD(AOldPlay.FGame) of
        ORD('R') : begin
          // Gewinner der ersten Runde
          if Odd(AOldPlay.Number) then begin
            NewPlay := GetPlay('V', 1, (AOldPlay.Number+1) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer1 := APlayer;
          end else begin
            NewPlay := GetPlay('V', 1, (AOldPlay.Number) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer2 := APlayer;
          end;
        end;
        ORD('G') : begin
          // jo, da hab ich noch kein System entdeckt ???????????

        end;
        ORD('V') : begin
          // das wars dann, kein weiteres Spiel :-(
          // oder doch? :-)  hab ich das System aber auch noch nicht durchschaut
        end;
      end;
    end;
  end;

begin
  // ein Spieler ist ein Freilos?
  if ((AProperty = 'Player1') or (AProperty = 'Player2')) and
     (Assigned(APlayClass.Player1) and Assigned(APlayClass.Player2)) and
     ((APlayClass.Player1.FPlayerType = pt_Looser) or (APlayClass.Player2.FPlayerType = pt_Looser)) then begin
    if APlayClass.Player1.FPlayerType = pt_Looser then begin
      // Player2 hat gewonnen
      AWinner := APlayClass.FPlayer2;
      ALooser := APlayClass.FPlayer1;
    end else begin
      // Player1 hat gewonnen
      AWinner := APlayClass.Player1;
      ALooser := APlayClass.Player2;
    end;
    // neues Spiel für Gewinner ermitteln
    PlayerinGame(AWinner, APlayClass, True);
    // neues Spiel für Verlierer ermitteln
    PlayerinGame(ALooser, APlayClass, False);

    // Counter der gespielten Spiele der Spieler erhöhen
    AWinner.PlayCount := AWinner.PlayCount + 1;
    ALooser.PlayCount := ALooser.PlayCount + 1;

    // aktuelle Platzierung der Spieler setzen
    AWinner.Position := FPlayerList.Count - AWinner.PlayCount;
    ALooser.Position := FPlayerList.Count - ALooser.PlayCount - 1;

    // Spielstatus auf beendet
    APlayClass.Status := ps_finish;
    Exit;
  end;

  // der Spielstand hat sich geändert
  if AProperty = 'PlayResult' then begin
    if (APlayClass.FPlayResult.Player1 <> 0) or (APlayClass.FPlayResult.Player2 <> 0) then begin
      // es gibt einen Spielstand <> 0
      if APlayClass.FPlayResult.Player1 > APlayClass.PlayResult.Player2 then begin
        // Player1 hat gewonnen
        AWinner := APlayClass.Player1;
        ALooser := APlayClass.Player2;
      end else begin
        // Player2 hat gewonnen
        AWinner := APlayClass.Player2;
        ALooser := APlayClass.Player1;
      end;
      // neues Spiel für Gewinner ermitteln
      PlayerinGame(AWinner, APlayClass, True);
      // neues Spiel für Verlierer ermitteln
      PlayerinGame(ALooser, APlayClass, False);

      // Counter der gespielten Spiele der Spieler erhöhen
      AWinner.PlayCount := AWinner.PlayCount + 1;
      ALooser.PlayCount := ALooser.PlayCount + 1;

      // aktuelle Platzierung der Spieler setzen
      AWinner.Position := FPlayerList.Count - AWinner.PlayCount;
      ALooser.Position := FPlayerList.Count - ALooser.PlayCount - 1;

      // Spielstatus auf beendet
      APlayClass.Status := ps_finish;
    end;
  end;
end;
Hier noch einige Bemerkungen zum Ablauf. Wird in einem Spiel ein Spielstand (oder eine andere Eigenschaft) geändert so ruft das Spiel die Procedure ChangePlay seiner PlayList auf und übergibt sich selbst sowie den Namen der Eigenschaft an die Procedure.
Die Procedure der PlayList macht jetzt folgendes. Erstens wird geschaut, ob der geänderte Parameter des Spiels der Spielstand oder der Typ des Spielers ist (Freilos bei Spieler). Ist ein gültiger Spielstand eingetragen, so wird der Gewinner und Verlierer des Spiels ermittelt. Dann werden diese an die Procedure PlayerinGame übergeben. Diese erhält folgender Werte:
APlayer = Spieler der in ein neues Spiel eingetragen werden soll
AOldPlay = Spiel das gerade zu Ende gespielt wurde
winning = gibt an, ob der Spieler der Gewinner oder Verlierer des Spieles ist.

Nun prüft die Procedure erst mal, welches Spiel das gerade gespielte Spiel ist, um das neue Spiel zu ermitteln, in das der aktuelle Spieler jetzt eingetragen werden soll.
Der erste Block der Abfrage für den Gewinner sollte eigentlich soweit ok sein. Keinen Plan hab ich noch für den zweiten Block, Eintrag des Verlierers. Das vorallem wenn er ein V- oder G-Spiel verloren hat.

Da die Procedure eine eigene Methode der PlayList ist, wird hier auf eigene Hilfsfunktionen zugegriffen. Das ist z.B. die Funktion GetPlay. GetPlay sucht in der Liste nach einem Spiel mit der angegebenen Bezeichnung und gibt die Instanz dieses Spieles als Ergebnis zurück. Wurde kein Spiel mit dieser Bezeichnung gefunden, so liefert die Funktion nil.
Das ergibt natürlich, dass in der Liste alle Spiele schon eingetragen sind. Erledigt wird das bei der Übergabe der Spielerliste an die PlayList. Dabei wird auf Basis der Anzahl der in der PlayerList eingetragenen Spieler der gesamte Spielplan automatisch erstellt und alle Spiele eingetragen. Das ist auch schon fertig und hat so keine großen Probleme bereitet. Hier mal diese Funktion zur Kontrolle:
Delphi-Quellcode:
procedure TPlayList.UpdatePlayCount;
var APlayerCount : Integer;
    Counter, CRound : Integer;

  procedure AddPlays(AGame : Char; ARound, ANumberCount : Integer);
  var BCounter : Integer;
  begin
    for BCounter := 1 to ANumberCount div 2 - 1 do begin
      if not Assigned(GetPlay(AGame, ARound, BCounter)) then begin
        // Spiel ist noch nicht angelegt
        Add(TPlayClass.Create(AGame, ARound, BCounter));
      end;
    end;
  end;

begin
  if not Assigned(FPlayerList) or (FPlayerList.Count = 0) then begin
    Clear;
  end else begin
    Clear;
    APlayerCount := FPlayerList.Count;
    // bei ungerade Anzahl von Spielern einen dazu
    if odd(APlayerCount) then
      inc(APlayerCount);

    // R-Spiele anlegen
    AddPlays('R', 1, APlayerCount div 2);

    // G-Spiele anlegen
    Counter := APlayerCount div 4;
    CRound := 1;
    while (Frac(Counter/2) = 0) do begin
      AddPlays('G', CRound, Counter);
      inc(CRound);
      Counter := Counter div 2;
    end;

    // V-Spiele anlegen
    Counter := APlayerCount div 4;
    CRound := 1;
    while (Frac(Counter/2) = 0) do begin
      AddPlays('V', CRound, Counter);
      inc(CRound);
      if not odd(CRound) then
        Counter := Counter div 2;
    end;

    // Finale anlegen
    Add(TPlayClass.Create('F', 0, 0));
  end;
end;
Du brauchst die Methoden hier nicht rauskopieren. Ich hab die Unit mit den Klassen schon fertig und hänge sie hier bei einem der nächsten Beiträge mit ran, dann kannst du sie dir direkt downloaden.

Ja, somit müssen wir nur noch die kleinen Probleme mit der Spielzuordnung für die Verlierer lösen und das Datenmodell ist fertig.
Dann können wir uns um den visuellen Teil kümmern.

Dann bis die Tage,

Gruß oki

Optiplex 9. Jun 2009 14:46

Re: Neue Komponente mit 2 TEdit Komponenten
 
hallo Oki,
ich werde versuchen dir den Ablauf zu erklären, nimm bitte dazu den Spielplan den ich hier mal an ein post von mir angehängt habe zur Hand.

R ist Runde1 hier beginnt das Turnier.
Die Anzahl der Spieler beträgt entweder 8 oder 16 oder 32 oder 64 usw., sonst funktioniert ein Doppel KO System nicht.
Die Gewinner jeder Paarung gehen in die Gewinnerrunde G1 die Verlierer in die Verliererrunde V1.
Der Gewinner der Gewinnerrunde G1 geht weiter in die Gewinnerrunde G2
der Verlierer der Gewinnerrunde G1 geht in die Verliererrunde V2 und war an die jeweilige Position A,B,C usw. (gelbes Kästchen unterhalb der Paarung) welche bei der Gewinnerrunde G1 angegeben ist (Verlierer -> A).
Der Verlierer aus der Verliererrunde V1 scheidet aus dem Turnier aus, weil er ein zweites mal verloren hat, der Gewinner der Verliererrunde V1 kommt weiter in die Verliererrunde V2 und trifft dort mit einem Verlierer aus der ersten Gewinnerrunde G1 zusammen.
Schau dir den Plan genau an, dann weist du wann ein Verlierer der Gewinnerrunde in die Verlierrunde kommt und an welcher Position er weiterspielt, den Zwischendurch gibt es auch runden bei den Paarung rein von der Verlierrunde zusammentreffen(haben kein gelbes Kasten unterhalb der Paarung).

Der Automat gehört nur bedingt zur Paarung, er ist für den eigentlichen Ablauf nicht notwendig.(praktisch nur der Spielort wo das Spiel stattfindet) sollte aber bei der paarung dabei sein wegen der Übersichtlichkeit.

Ich hoffe, dass du das nun verstanden hast, solltest du dennoch noch fragen haben, stehe ich dir gerne zur Verfügung.

bis dann Dieter

oki 9. Jun 2009 16:27

Re: Neue Komponente mit 2 TEdit Komponenten
 
Hallo optiplex,

soweit habe ich den Spielplan verstanden. Der Punkt ist, dass es Sinn macht ein allgemeines Zuordnungsprinzip, einen Algorithmus zu finden, mit dem man mathematisch das nächste Spiel ermitteln kann. Somit wird die procedure universell und gilt für alle Anzahlen von Spielern, egal ob 8, 16, 32 usw. Man muss halt nicht für jede Anzahl von Spielern eine eigene Zuordnungsprocedure schreiben. Das habe ich versucht, bin an der erwähnten Stelle gescheitert. Da hatte ich auch noch nicht begriffen, dass das KO-System auf eine Spieleranzahl zur Basis 8 definiert ist.

Ich erkläre mal meine Vorgehensweise für den Teil den ich bis jetzt in den Griff bekommen haben (dabei war die Annahme, dass ausschließlich eine gerade Anzahl von Spielern notwendig ist).

[edit] Sorry, hier noch mal was die Eigenschaften bei TPlayClass (und somit für den Parameter APlayClass) bedeuten.
Delphi-Quellcode:
    FGame: Char;               // Spiel; R, V, G
    FNumber: Integer;          // Spielnummer 1..x
    FPlayer1: TPlayerClass;    // Spieler 1
    FPlayer2: TPlayerClass;    // Spieler 2
    FPlayList: TPlayList;      // übergeordnete PlayList
    FPlayResult: TPlayResult;  // Ergebnis des Spiels
    FRound: Integer;           // Runde
    FStatus: TPlayState;       // Spielstatus
Bsp.:
R1-2
R = Game
1 = Round
2 = Number

- = nur optischer Trenner im String.
[/edit]

In der procedure wird der Spieler der einem neuen Spiel zugeordnet werden soll, das aktuell gespielte Spiel sowie ein Flag ob der übergebene Spieler der Gewinner der Partie war übergeben:
Delphi-Quellcode:
procedure TPlayList.ChangePlay(APlayClass: TPlayClass; AProperty : String);
Als erstes prüfe ich, ob der Spieler der einem neuen Spiel zugeordnet werden soll ein Gewinner ist:
Delphi-Quellcode:
    if winning then begin
      // Spieler ist Gewinner des alten Spieles
Jetzt berücksichtige ich, welches Spiel das gerade gespielte Spiel war:
Delphi-Quellcode:
      case ORD(AOldPlay.FGame) of
        ORD('R') : begin
          // Gewinner der ersten Runde
Also, der Spieler hat in einer Runde 'R' (erste Spielrunde aller Spieler) gewonnen. Anhand des Spielplanes hab ich eine recht einfache logische Folge entdeckt. Der Gewinner einer Runde "R" geht wie folgt als Spieler in ein Spiel der Runde "G" :

Gewinner aus:
R1 wird erster Spieler G1
R2 wird zweiter Spieler G1
R3 wird erster Spieler G2
R4 wird zweiter Spielr G2
.... und endlos so weiter.
Daraus folgt, das der Gewinner aller ungeraden Spielnummern für "R" immer der erste Spieler des folgenden Gewinnerspieles wird und der Gewinner mit den geraden Spielnummern für "R" immer der zweite Spieler. Die Nummer des zu ermittelnden "G"-Spieles ist immer das Ergebnis die auf eine gerade Zahl aufgerundete Spielnummer von "R" geteilt durch 2.
R-Nummer wird zur G-Nummer
1 -> 1
2 -> 1
3 -> 2
4 -> 2
.........
17 -> 9
18 -> 9
19 -> 10
20 -> 10
.........
somit entstehr folgender Code:
Delphi-Quellcode:
          if Odd(AOldPlay.Number) then begin  // Gewinner einer ungeraden Spielrunde
            NewPlay := GetPlay('G', 1, (AOldPlay.Number+1) div 2);  // das Spiel "G1-x" holen, wobei x gleich (y+1)/2 aus R1-y für das ungerade Spiel ist
            if Assigned(NewPlay) then
              NewPlay.FPlayer1 := APlayer;    // wird Spieler 1 
          end else begin                      // Gewinner einer geraden Spielrunde
            NewPlay := GetPlay('G', 1, (AOldPlay.Number) div 2);    // // das Spiel "G1-x" holen, wobei x gleich y/2 aus R1-y für das gerade Spiel ist
            if Assigned(NewPlay) then
              NewPlay.FPlayer2 := APlayer;    // wird Spieler 2
          end;
Soweit so gut. Das lässt so einfach für alle Spieler ermitteln, die Gewinner einer Runde sind, Egal ob sie vorher einmal verloren haben. Ich denke unter dieser Erläuterung sollte der Code für die gewonnenen "G" und "V"-Spiele nachvollziehbar sein, auch wenn er einer etwas anderen Logik folgt.

In den weiteren Spielrunden für "G" und "V" prüfe ich zusätzlich, ob wirklich ein neues Spiel gefunden wurde. Ist dies nämlich nicht der Fall, so ist der Gewinner ein Teilnehmer für das Finale. Da gibt es keinen Ausweg.
Delphi-Quellcode:
            if Assigned(NewPlay) then begin
              NewPlay.FPlayer1 := APlayer;
            end else begin
              // das war das letzte Gewinnerspiel, ab ins Finale
              NewPlay := GetPlay('F', 0, 0);
              if Assigned(NewPlay) then
                NewPlay.Player1 := APlayer;
            end;
Dabei ist recht einfach zu erkennen, dass der Gewinner eines "G"-Spieles der erste Spieler des Finales und der Gewinner des "V"-Spieles der zweite Spieler des Finales wird (für mich ist das aber wurscht, es bleiben eh nur zwei übrig; wer das erster oder zweiter Spieler ist scheint wohl nur für die Profis wichtig zu sein).


Soweit war das alles recht logisch. Meine Probleme fangen mit den Verlierern der "G" und "V"-Spiele an. Für die Verlierer der R-Spiele ist das so einfach wie oben beschrieben bei den Gewinnern.

Ich habe folgendes gesehen (für 16 Spieler) Verlierer des Spiels geht in Spiel:
Gx-y -> Va-b
G1-1 -> V2-4 2.Spieler
G1-2 -> V2-3 2.Spieler
G1-3 -> V2-2 2.Spieler
G1-4 -> V2-1 2.Spieler

G2-1 -> V4-2 2.Spieler
G2-2 -> V4-1 2.Spieler

G3-1 -> V6-1 2.Spieler

da steckt auch ein System dahinter. Schau mal, ob du das umgesetzt bekommst. Das sollte rein mathematisch gehen. Ein Ansatz ist, dass für 16 Spieler 4 G1 Spiele existieren, wobei das Va-b Spiel a=x*2 und b=16/4-y-1 ist. x und y entnimmt man Gx-y. Jo, so klappts.

Das ganze muss jetzt noch für die Verliererspiele ausgetüftelt werden.

Läßt sich mit dem neu ermittelten Spielnamen kein Spiel in der Spielliste finden, so ist das Turnier für diesen Spieler zu ende. Die Berechnung der Platzierung ist bei mir noch falsch, aber dazu später.

Gruß oki

oki 9. Jun 2009 16:36

Re: Neue Komponente mit 2 TEdit Komponenten
 
Ähhm, das sieht jetzt aber nicht so schwer aus:
Delphi-Quellcode:
      // Spieler ist Verlierer des alten Spieles
      case ORD(AOldPlay.FGame) of
        ORD('R') : begin
          // Gewinner der ersten Runde
          if Odd(AOldPlay.Number) then begin
            NewPlay := GetPlay('V', 1, (AOldPlay.Number+1) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer1 := APlayer;
          end else begin
            NewPlay := GetPlay('V', 1, (AOldPlay.Number) div 2);
            if Assigned(NewPlay) then
              NewPlay.FPlayer2 := APlayer;
          end;
        end;
        ORD('G') : begin
          NewPlay := GetPlay('V', AOldPlay.Round*2, 16/4 - AOldPlay.Number - 1);
          if Assigned(NewPlay) then
            NewPlay.FPlayer2 := APlayer;
        end;
        ORD('V') : begin
          // das wars dann, kein weiteres Spiel :-(
          // oder doch? :-)  hab ich das System aber auch noch nicht durchschaut
        end;
      end;
"V"-Spiele muss noch. Neu ist der Teil:
Delphi-Quellcode:
        ORD('G') : begin
          NewPlay := GetPlay('V', AOldPlay.Round*2, 16/4 - AOldPlay.Number - 1);
          if Assigned(NewPlay) then
            NewPlay.FPlayer2 := APlayer;
        end;
umgesetzt wie vorher beschrieben. Sieht irgendwie zu einfach aus. :gruebel:

Hab ich da was verpennt?

Gruß oki

Optiplex 10. Jun 2009 08:19

Re: Neue Komponente mit 2 TEdit Komponenten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Olaf,
das mit der Basis 8 ist falsch,
damit ein Spielplan aufgeht egal ob Doppel KO oder einfach KO benötigst du immer 2,4,8,16,32,64,128 usw spieler sonst geht das Turnier einfach nicht auf. deshaslb musst du fehlende Spieler durch Freilose ersetzen und diese Freilose must du an bestimmten stellen einsetzen damit jedes Freilos Spätestens in der 2 Verliererrund ausscheidet.
Siehe Beispiel (Anhang Plan.jpg) dies sind 12 Parungen=24 Spieler und das Turnier geht nicht auf.

Ist ein Spieler in der Verliererrunde und verliert dann ist er ausgeschieden hier kommt nur der Gewinner weiter.


Ich habe dir gleich gesagt, dass es so einfach nicht ist, wie du dir das am Anfang vorgestellt hast.

Gruss Dieter


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:30 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz