Commit 64b24cf17cd7d3f1e52b2ba0b05b477597b8846b

Authored by Carlos Picanco
1 parent 675bd299
Exists in master

fully implement prompts, real time report, and dumps

cultural_matrix.lpi
... ... @@ -55,7 +55,7 @@
55 55 <PackageName Value="LCL"/>
56 56 </Item2>
57 57 </RequiredPackages>
58   - <Units Count="14">
  58 + <Units Count="15">
59 59 <Unit0>
60 60 <Filename Value="cultural_matrix.lpr"/>
61 61 <IsPartOfProject Value="True"/>
... ... @@ -117,6 +117,10 @@
117 117 <ComponentName Value="FormChooseActor"/>
118 118 <ResourceBaseClass Value="Form"/>
119 119 </Unit13>
  120 + <Unit14>
  121 + <Filename Value="units/csv_writer.pas"/>
  122 + <IsPartOfProject Value="True"/>
  123 + </Unit14>
120 124 </Units>
121 125 </ProjectOptions>
122 126 <CompilerOptions>
... ...
cultural_matrix.lpr
... ... @@ -35,7 +35,9 @@ var
35 35 I : integer;
36 36 {$ENDIF}
37 37 ID : TStringList;
  38 + ApplicationPath,
38 39 F : string;
  40 +
39 41 const
40 42 PAdmin : array [0..3] of string = ('--admin','--adm','-admin','-adm');
41 43 PPlayer : array [0..3] of string = ('--player','--play','-player','-play');
... ... @@ -43,50 +45,68 @@ const
43 45  
44 46 {$R *.res}
45 47  
  48 +
  49 +{$IFDEF DEBUG}
  50 + function CreateDebugFoldersForPlayers:Boolean;
  51 + var
  52 + i : integer;
  53 + begin
  54 + Result := True;
  55 + for i := 0 to 2 do
  56 + begin
  57 + if Pos((PathDelim+'P'+IntToStr(i+1)+PathDelim), Application.ExeName) > 0 then
  58 + Break;
  59 + F := ApplicationPath+'P'+IntToStr(i+1);
  60 + WriteLn(F);
  61 + if ForceDirectoriesUTF8(F) then // ensure we have always the newer version for tests
  62 + begin
  63 + CopyFile(Application.ExeName,F+PathDelim+ApplicationName,[cffOverwriteFile]);
  64 + {$IFDEF LINUX}
  65 + FpChmod(F+PathDelim+ApplicationName,S_IRWXU);
  66 + {$ENDIF}
  67 + end
  68 + else Result := False;
  69 + end;
  70 + end;
  71 +{$ENDIF}
  72 +
  73 + function GetZMQNetworkID(var F:string):Boolean;
  74 + begin
  75 + Result := True;
  76 + ID := TStringList.Create;
  77 + if FileExists(F) then
  78 + try
  79 + ID.LoadFromFile(F);
  80 + F := Copy(ID.Text,0,Length(ID.Text)-2);
  81 + finally
  82 + ID.Free;
  83 + end
  84 + else
  85 + try
  86 + ID.Text := s_random(32);
  87 + ID.SaveToFile(F);
  88 + F := Copy(ID.Text,0,Length(ID.Text)-2);
  89 + except
  90 + on E: Exception do
  91 + begin
  92 + ID.Free;
  93 + {$IFDEF DEBUG}
  94 + ShowMessage(E.Message);
  95 + {$ENDIF}
  96 + Result := False;
  97 + end;
  98 + end;
  99 + end;
  100 +
46 101 begin
  102 + ApplicationPath := ExtractFilePath(Application.ExeName);
47 103 {$IFDEF DEBUG}
48   - for i:= 0 to 2 do
49   - begin
50   - if Pos((PathDelim+'P'+IntToStr(i+1)+PathDelim), Application.ExeName) > 0 then
51   - Break;
52   - F := ExtractFilePath(Application.ExeName)+'P'+IntToStr(i+1);
53   - WriteLn(F);
54   - if ForceDirectoriesUTF8(F) then // ensure we have always the newer version for tests
55   - begin
56   - CopyFile(Application.ExeName,F+PathDelim+ApplicationName,[cffOverwriteFile]);
57   - {$IFDEF LINUX}
58   - FpChmod(F+PathDelim+ApplicationName,S_IRWXU);
59   - {$ENDIF}
60   - end
61   - else Exit;
62   - end;
  104 + if not CreateDebugFoldersForPlayers then Exit;
63 105 {$ENDIF}
64 106 Application.Initialize;
65   - F := ExtractFilePath(Application.ExeName)+PathDelim+'id';
66   - ID := TStringList.Create;
67   - if FileExists(F) then
68   - try
69   - ID.LoadFromFile(F);
70   - F := Copy(ID.Text,0,Length(ID.Text)-2);
71   - finally
72   - ID.Free;
73   - end
74   - else
75   - try
76   - ID.Text := s_random(32);
77   - ID.SaveToFile(F);
78   - F := Copy(ID.Text,0,Length(ID.Text)-2);
79   - except
80   - on E: Exception do
81   - begin
82   - ID.Free;
83   - {$IFDEF DEBUG}
84   - ShowMessage(E.Message);
85   - {$ENDIF}
86   - Exit;
87   - end;
88   - end;
89   - Application.CreateForm(TFormMatrixGame, FormMatrixGame);
  107 + F := ApplicationPath+PathDelim+'id';
  108 + if not GetZMQNetworkID(F) then Exit;
  109 + Application.CreateForm(TFormMatrixGame, FormMatrixGame);
90 110  
91 111 FormMatrixGame.SetID(F);
92 112 if Paramcount > 0 then
... ...
form_matrixgame.pas
... ... @@ -72,14 +72,14 @@ type
72 72 procedure ButtonExpStartClick(Sender: TObject);
73 73 procedure ChatMemoSendKeyPress(Sender: TObject; var Key: char);
74 74 procedure FormActivate(Sender: TObject);
75   - procedure PopupNotifierClose(Sender: TObject; var CloseAction: TCloseAction
76   - );
  75 + procedure PopupNotifierClose(Sender: TObject; var CloseAction: TCloseAction);
77 76 procedure StringGridMatrixClick(Sender: TObject);
78 77 procedure StringGridMatrixDrawCell(Sender: TObject; aCol, aRow: integer;
79 78 aRect: TRect; aState: TGridDrawState);
80 79 procedure TimerTimer(Sender: TObject);
81 80 private
82 81 FGameControl : TGameControl;
  82 + FAppPath,
83 83 FID: string;
84 84 public
85 85 procedure SetID(S : string);
... ... @@ -106,7 +106,6 @@ procedure TFormMatrixGame.StringGridMatrixDrawCell(Sender: TObject; aCol, aRow:
106 106 aRect: TRect; aState: TGridDrawState);
107 107 var
108 108 OldCanvas: TCanvas;
109   - RowBase : integer;
110 109  
111 110 procedure SaveOldCanvas;
112 111 begin
... ... @@ -157,8 +156,8 @@ var
157 156 TStringGrid(Sender).Canvas.Rectangle(aRect);
158 157 if Assigned(FGameControl) then
159 158 if FGameControl.MustDrawDots then
160   - if (Odd(aRow + RowBase) and not Odd(aCol)) or
161   - (not Odd(aRow + RowBase) and Odd(aCol)) then
  159 + if (Odd(aRow + FGameControl.RowBase) and not Odd(aCol)) or
  160 + (not Odd(aRow + FGameControl.RowBase) and Odd(aCol)) then
162 161 DrawDots;
163 162 end;
164 163 //function GetTextX(S : String): Longint;
... ... @@ -167,15 +166,14 @@ var
167 166 //end;
168 167  
169 168 begin
170   - if Assigned(FGameControl) then
171   - RowBase:=FGameControl.RowBase;
  169 + if not Assigned(FGameControl) then Exit;
172 170 SaveOldCanvas;
173 171 try
174 172 //if (aRow >= RowBase) and (aCol = 10) then
175 173 // DrawLines(clWhite);
176   - if (aCol <> 0) and (aRow > (RowBase-1)) then
  174 + if (aCol <> 0) and (aRow > (FGameControl.RowBase-1)) then
177 175 begin
178   - DrawLines(GetRowColor(aRow,RowBase));
  176 + DrawLines(GetRowColor(aRow,FGameControl.RowBase));
179 177  
180 178 if (gdSelected in aState) and (goRowSelect in TStringGrid(Sender).Options)then
181 179 begin
... ... @@ -226,13 +224,13 @@ procedure TFormMatrixGame.SetGameActor(AValue: TGameActor);
226 224  
227 225 procedure SetZMQAdmin;
228 226 begin
229   - FGameControl := TGameControl.Create(TZMQAdmin.Create(Self,FID));
  227 + FGameControl := TGameControl.Create(TZMQAdmin.Create(Self,FID),ExtractFilePath(Application.ExeName));
230 228 GBAdmin.Visible:= True;
231 229 end;
232 230  
233 231 procedure SetZMQPlayer;
234 232 begin
235   - FGameControl := TGameControl.Create(TZMQPlayer.Create(Self,FID));
  233 + FGameControl := TGameControl.Create(TZMQPlayer.Create(Self,FID),ExtractFilePath(Application.ExeName));
236 234 //StringGridMatrix.Enabled := True;
237 235 end;
238 236  
... ... @@ -257,24 +255,27 @@ end;
257 255  
258 256 procedure TFormMatrixGame.FormActivate(Sender: TObject);
259 257 begin
260   - FormChooseActor := TFormChooseActor.Create(Self);
261   - FormChooseActor.Style := '.Arrived';
262   - try
263   - if FormChooseActor.ShowModal = 1 then
264   - begin
265   - case FormChooseActor.GameActor of
266   - gaAdmin:FormMatrixGame.SetGameActor(gaAdmin);
267   - gaPlayer: FormMatrixGame.SetGameActor(gaPlayer);
268   - gaWatcher: FormMatrixGame.SetGameActor(gaWatcher);
269   - end;
270   - StringGridMatrix.ClearSelections;
271   - StringGridMatrix.FocusRectVisible := False;
272   - FGameControl.SetMatrix;
273   - end
274   - else Close;
275   - finally
276   - FormChooseActor.Free;
277   - end;
  258 + if not Assigned(FGameControl) then
  259 + begin
  260 + FormChooseActor := TFormChooseActor.Create(Self);
  261 + FormChooseActor.Style := '.Arrived';
  262 + try
  263 + if FormChooseActor.ShowModal = 1 then
  264 + begin
  265 + case FormChooseActor.GameActor of
  266 + gaAdmin:FormMatrixGame.SetGameActor(gaAdmin);
  267 + gaPlayer: FormMatrixGame.SetGameActor(gaPlayer);
  268 + gaWatcher: FormMatrixGame.SetGameActor(gaWatcher);
  269 + end;
  270 + StringGridMatrix.ClearSelections;
  271 + StringGridMatrix.FocusRectVisible := False;
  272 + FGameControl.SetMatrix;
  273 + end
  274 + else Close;
  275 + finally
  276 + FormChooseActor.Free;
  277 + end;
  278 + end;
278 279 end;
279 280  
280 281 procedure TFormMatrixGame.PopupNotifierClose(Sender: TObject;
... ...
units/csv_writer.pas 0 → 100644
... ... @@ -0,0 +1,98 @@
  1 +unit csv_writer;
  2 +
  3 +{$mode objfpc}{$H+}
  4 +
  5 +interface
  6 +
  7 +uses SysUtils, Classes, LazFileUtils;
  8 +
  9 +type
  10 +
  11 + { TCSVWriter }
  12 +
  13 + TCSVWriter = class(TComponent)
  14 + private
  15 + FFileName: string;
  16 + FFile: TextFile;
  17 + FSessionNumber: integer;
  18 + procedure Close;
  19 + procedure UpdateFileName(ANewFileName : string);
  20 + function OpenNoOverride(AFilename : string):string;
  21 + public
  22 + constructor Create(AOwner: TComponent; AFileName: String); reintroduce;
  23 + destructor Destroy; override;
  24 + procedure Write(AData: array of const);
  25 + end;
  26 +
  27 +
  28 +
  29 +
  30 +implementation
  31 +
  32 +{ TCSVWriter }
  33 +
  34 +procedure TCSVWriter.Close;
  35 +begin
  36 + if FFilename <> '' then
  37 + if TextRec(FFile).Mode = 55218 then // file is opened read/write
  38 + begin
  39 + CloseFile(FFile);
  40 + end
  41 +end;
  42 +
  43 +procedure TCSVWriter.UpdateFileName(ANewFileName: string);
  44 +begin
  45 + if (ANewFileName = '') or (ANewFileName = FFilename) then Exit;
  46 + Close;
  47 + FFileName := OpenNoOverride(ANewFileName);
  48 +end;
  49 +
  50 +function TCSVWriter.OpenNoOverride(AFilename: string): string;
  51 +var
  52 + i : Integer;
  53 + FilePath, LExtension: string;
  54 +begin
  55 + if AFileName <> '' then
  56 + begin
  57 + ForceDirectoriesUTF8(ExtractFilePath(AFilename));
  58 + FilePath := ExtractFilePath(AFilename);
  59 + LExtension := ExtractFileExt(AFilename);
  60 + i := 0;
  61 +
  62 + // ensure to never override an existing file
  63 + while FileExistsUTF8(AFilename) do begin
  64 + Inc(i);
  65 + AFilename := FilePath + StringOfChar(#48, 3 - Length(IntToStr(i))) + IntToStr(i) + LExtension;
  66 + end;
  67 +
  68 + FSessionNumber := i;
  69 +
  70 + // as override is impossible, don't mind about an Assign/Rewrite conditional
  71 + AssignFile(FFile, AFilename);
  72 + Rewrite(FFile);
  73 + {$ifdef DEBUG}
  74 + WriteLn(FFile, mt_Debug + 'Saving data to:' + AFilename );
  75 + {$endif}
  76 + Result := AFilename;
  77 + end;
  78 +end;
  79 +
  80 +constructor TCSVWriter.Create(AOwner: TComponent; AFileName: String);
  81 +begin
  82 + inherited Create(AOwner);
  83 + FFilename := OpenNoOverride(AFilename);
  84 +end;
  85 +
  86 +destructor TCSVWriter.Destroy;
  87 +begin
  88 + Close;
  89 + inherited Destroy;
  90 +end;
  91 +
  92 +procedure TCSVWriter.Write(AData: array of const);
  93 +begin
  94 +
  95 +end;
  96 +
  97 +end.
  98 +
... ...
units/game_actors.pas
... ... @@ -106,6 +106,7 @@ type
106 106 destructor Destroy;override;
107 107 function AsString(AID :string): string;
108 108 function GenerateMessage(ForGroup: Boolean):string;
  109 + procedure Clean; virtual;
109 110 procedure PresentMessage;
110 111 procedure PresentPoints;
111 112 property ShouldPublishMessage : Boolean read GetShouldPublishMessage;
... ... @@ -123,6 +124,7 @@ type
123 124 FMeta : Boolean; //True: Consequence occurs OnEndTurn, False: Consequence occurs OnEndCycle
124 125 FConsequence : TConsequence;
125 126 FCriteria : TCriteria;
  127 + FName: string;
126 128 FOnCriteria: TNotifyEvent;
127 129 function RowMod(R:TGameRow):TGameRow;
128 130 procedure CriteriaEvent;
... ... @@ -131,11 +133,14 @@ type
131 133 function CriteriaString : string;
132 134 function ResponseMeetsCriteriaI(R : TGameRow; C : TGameColor):Boolean; // Does response meets operant criteria?
133 135 function ResponseMeetsCriteriaG(Players : TPlayers):Boolean;
  136 + function ConsequenceFromPlayerID(AID:string):string;
  137 + procedure Clean;
134 138 property OnCriteria : TNotifyEvent read FOnCriteria write FOncriteria;
135 139 property Fired : Boolean read FFired;
136 140 property Consequence : TConsequence read FConsequence;
137 141 property Criteria : TCriteria read FCriteria;
138 142 property Meta : Boolean read FMeta;
  143 + property ContingencyName : string read FName write FName;
139 144 end;
140 145  
141 146 { TContingencies }
... ... @@ -155,8 +160,9 @@ type
155 160 public
156 161 constructor Create(AOwner:TComponent; APStyle:TPromptStyle; APTarget : TContingencies; AMessage:string);reintroduce;
157 162 function ResponsesCount : integer;
158   - procedure AppendResponse(AID,R:string);
159 163 function AsString: TStringList; overload;
  164 + procedure AppendResponse(AID,R:string);
  165 + procedure Clean;override;
160 166 property Question: string read FPromptMessage;
161 167 property PromptResult:string read FResult;
162 168  
... ... @@ -398,6 +404,17 @@ begin // All -&gt; (Diff,Equal,Even, Odd) or not all
398 404 CriteriaEvent;
399 405 end;
400 406  
  407 +function TContingency.ConsequenceFromPlayerID(AID: string): string;
  408 +begin
  409 + Result := Consequence.ConsequenseByPlayerID.Values[AID];
  410 +end;
  411 +
  412 +procedure TContingency.Clean;
  413 +begin
  414 + FFired := False;
  415 + Consequence.Clean;
  416 +end;
  417 +
401 418  
402 419 { TPrompt }
403 420  
... ... @@ -426,6 +443,12 @@ begin
426 443 FResponses[High(FResponses)] := AID+'|'+R+'|';
427 444 end;
428 445  
  446 +procedure TPrompt.Clean;
  447 +begin
  448 + //inherited Clean;
  449 + FResponses := nil;
  450 +end;
  451 +
429 452 function TPrompt.AsString: TStringList;
430 453 var
431 454 j,i : integer;
... ... @@ -454,8 +477,8 @@ var
454 477  
455 478 if (gscB in LCsqStyle) and (gsBasA in FPromptStyle) then
456 479 begin
457   - LCsqStyle += [gscB];
458   - LCsqStyle -= [gscA];
  480 + LCsqStyle += [gscA];
  481 + LCsqStyle -= [gscB];
459 482 end;
460 483  
461 484 if IsMeta then
... ... @@ -471,17 +494,22 @@ var
471 494 ExtractDelimited(5,LConsequence, ['|']);
472 495 end;
473 496 begin
  497 + Result := TStringList.Create;
474 498 // to do, sanitize FPromptStyle first
475 499 Pts:= 0;
476 500 if (gsAll in FPromptStyle) and (gsYes in FPromptStyle) then
477 501 if AllPlayersClickedYes then
478 502 for i := 0 to Length(FPromptTargets)-1 do
479   - for j := 0 to FPromptTargets[i].Consequence.ConsequenseByPlayerID.Count do
  503 + for j := 0 to FPromptTargets[i].Consequence.ConsequenseByPlayerID.Count-1 do
480 504 begin
481 505 LID := FPromptTargets[i].Consequence.ConsequenseByPlayerID.Names[j];
482 506 LConsequence := FPromptTargets[i].Consequence.ConsequenseByPlayerID.Values[LID];
483 507 LCsqStyle := GetConsequenceStylesFromString(ExtractDelimited(2,LConsequence, ['|']));
484 508  
  509 + // TODO: should BasA revert appendices? right now reverting points only
  510 + //LAppendiceSingular:=
  511 + //LAppendicePlural:=
  512 +
485 513 if gsContingency in FPromptStyle then
486 514 if (FPromptTargets[i].Fired) and (not FPromptTargets[i].Meta) then
487 515 if (gscA in LCsqStyle) or (gscB in LCsqStyle) then
... ... @@ -493,7 +521,7 @@ begin
493 521 if gscG in LCsqStyle then
494 522 ApplyPointsConditions(True);
495 523  
496   - Result := TStringList.Create;
  524 +
497 525 Result.Add(LConsequence);
498 526 end;
499 527  
... ... @@ -541,7 +569,7 @@ begin
541 569 FMessage := TPopupNotifier.Create(Self);
542 570 FTimer := TTimer.Create(Self);
543 571 FTimer.Enabled:=False;
544   - FTimer.Interval:=6000;
  572 + FTimer.Interval:=10000;
545 573 FTimer.OnTimer:=@SelfDestroy;
546 574 FConsequenceByPlayerID := TStringList.Create;
547 575 end;
... ... @@ -568,27 +596,25 @@ begin
568 596 FMessage.Text := Result;
569 597 end;
570 598  
  599 +procedure TConsequence.Clean;
  600 +begin
  601 + FConsequenceByPlayerID.Clear;
  602 +end;
  603 +
571 604 procedure TConsequence.PresentMessage;
572 605 var
573 606 PopUpPos : TPoint;
574 607 begin
  608 + PopUpPos.X := FormMatrixGame.GBIndividualAB.Left;
575 609 if gscA in FStyle then
576   - begin
577   - PopUpPos.X := FormMatrixGame.GBIndividualAB.Left-110;
578   - PopUpPos.Y := FormMatrixGame.GBIndividualAB.Top+FormMatrixGame.GBIndividual.Height-10;
579   - end;
  610 + PopUpPos.Y := FormMatrixGame.GBIndividualAB.Top+FormMatrixGame.GBIndividualAB.Height-20;
580 611  
581 612 if gscB in FStyle then
582   - begin
583   - PopUpPos.X := FormMatrixGame.GBIndividualAB.Left+110;
584   - PopUpPos.Y := FormMatrixGame.GBIndividualAB.Top+FormMatrixGame.GBIndividual.Height-10;
585   - end;
  613 + PopUpPos.Y := FormMatrixGame.GBIndividualAB.Top+FormMatrixGame.GBIndividualAB.Height+150;
586 614  
587 615 if gscG in FStyle then
588   - begin
589   - PopUpPos.X := FormMatrixGame.GBIndividualAB.Left-110;
590   - PopUpPos.Y := FormMatrixGame.GBIndividualAB.Top+FormMatrixGame.GBIndividual.Height+100;
591   - end;
  616 + PopUpPos.Y := FormMatrixGame.GBIndividualAB.Top+FormMatrixGame.GBIndividualAB.Height+300;
  617 +
592 618 PopUpPos := FormMatrixGame.ClientToScreen(PopUpPos);
593 619 FMessage.Color:=clTeal;
594 620 FMessage.Title:='';
... ...
units/game_actors_point.pas
... ... @@ -73,7 +73,7 @@ end;
73 73  
74 74 function TGamePoint.GetResultAsString: string;
75 75 begin
76   - Result := IntToStr(FResult);
  76 + Result := IntToStr(abs(FResult));
77 77 end;
78 78  
79 79 constructor TGamePoint.Create(AOwner: TComponent; AValue: integer);
... ... @@ -111,7 +111,7 @@ begin
111 111 case FResult of
112 112 -MaxInt..-2: Result += ' produziram a perda de '+Self.AsString+ ' pontos para o grupo';
113 113 -1 : Result += ' produziram a perda de 1 ponto para o grupo';
114   - 0 : Result += ' pontos do grupo não foram produzidos nem perdidos';
  114 + 0 : Result += ' não produziram nem perderam pontos para o grupo';
115 115 1 : Result += ' produziram 1 ponto para o grupo';
116 116 2..MaxInt: Result += ' produziram '+Self.AsString+' pontos para o grupo'
117 117 end;
... ... @@ -119,11 +119,11 @@ begin
119 119 else
120 120 begin
121 121 case FResult of
122   - -MaxInt..-2: Result += ' produziram a perda de '+Self.AsString+ ' ' + AAppendicePlural;
123   - -1 : Result += ' produziram a perda de 1'+ ' ' + AAppendiceSingular;
124   - 0 : Result += ' não produziram ' + AAppendicePlural;
  122 + -MaxInt..-2: Result += ' produziram a perda de ' + Self.AsString + ' ' + AAppendicePlural;
  123 + -1 : Result += ' produziram a perda de 1 ' + AAppendiceSingular;
  124 + 0 : Result += ' não produziram nem perderam ' + AAppendicePlural;
125 125 1 : Result += ' produziram 1 ' + AAppendiceSingular;
126   - 2..MaxInt: Result += ' produziram '+Self.AsString+ ' ' + AAppendicePlural;
  126 + 2..MaxInt: Result += ' produziram ' + Self.AsString + ' ' + AAppendicePlural;
127 127 end;
128 128 end;
129 129 end
... ... @@ -148,7 +148,7 @@ begin
148 148 begin
149 149 case FResult of
150 150 -MaxInt..-2: Result += ' perdeu '+Self.AsString+ ' ' + AAppendicePlural;
151   - -1 : Result += ' ponto 1 ' + AAppendiceSingular;
  151 + -1 : Result += ' perdeu 1 ' + AAppendiceSingular;
152 152 0 : Result += ' não perdeu nem ganhou ' + AAppendicePlural;
153 153 1 : Result += ' ganhou 1 ' + AAppendiceSingular;
154 154 2..MaxInt: Result += ' ganhou '+Self.AsString+ ' ' + AAppendicePlural;
... ...
units/game_control.pas
... ... @@ -54,10 +54,12 @@ type
54 54 private
55 55 function AskQuestion(AQuestion:string):UTF8string;
56 56 procedure ShowPopUp(AText:string);
  57 + procedure ShowConsequenceMessage(AID,S:string;ForGroup:Boolean);
57 58 procedure DisableConfirmationButton;
58 59 procedure CleanMatrix(AEnabled : Boolean);
59 60 procedure EnablePlayerMatrix(AID:UTF8string; ATurn:integer; AEnabled:Boolean);
60 61 private
  62 +
61 63 function ShouldStartExperiment: Boolean;
62 64 function ShouldEndCycle : Boolean;
63 65 function ShouldAskQuestion : Boolean;
... ... @@ -71,7 +73,7 @@ type
71 73 procedure EndExperiment(Sender: TObject);
72 74 procedure StartExperiment;
73 75 public
74   - constructor Create(AOwner : TComponent);override;
  76 + constructor Create(AOwner : TComponent;AppPath:string);overload;
75 77 destructor Destroy; override;
76 78 procedure SetMatrix;
77 79 procedure SendRequest(ARequest : UTF8string);
... ... @@ -145,15 +147,14 @@ begin
145 147 Result := FExperiment.PlayersCount = FExperiment.Condition[FExperiment.CurrentCondition].Turn.Value;
146 148 end;
147 149  
148   -function TGameControl.ShouldEndCycle: Boolean;
  150 +function TGameControl.ShouldEndCycle: Boolean; //CAUTION: MUST BE CALLED BEFORE EXPERIMENT.NEXTCYCLE
149 151 begin
150 152 Result := FExperiment.Condition[FExperiment.CurrentCondition].Turn.Count = FExperiment.Condition[FExperiment.CurrentCondition].Turn.Value-1;
151 153 end;
152 154  
153   -function TGameControl.ShouldAskQuestion: Boolean; // end cycle, restart alias
  155 +function TGameControl.ShouldAskQuestion: Boolean;
154 156 begin
155   - // TODO: prompt only when an odd row was selected
156   - Result := ShouldEndCycle and FExperiment.Condition[FExperiment.CurrentCondition].Contingencies[3].Fired;
  157 + Result := Assigned(FExperiment.Condition[FExperiment.CurrentCondition].Prompt) and FExperiment.Condition[FExperiment.CurrentCondition].Contingencies[3].Fired;
157 158 end;
158 159  
159 160 procedure TGameControl.KickPlayer(AID: string);
... ... @@ -169,24 +170,11 @@ begin
169 170 end;
170 171  
171 172 procedure TGameControl.NextCycle(Sender: TObject);
172   -var
173   - i,
174   - LCount : integer;
175   - LConsequences : string;
176 173 begin
177   - // prompt question to all players
178 174 FormMatrixGame.LabelExpCountCycle.Caption:=IntToStr(FExperiment.Condition[FExperiment.CurrentCondition].Cycles.Count+1);
179 175 {$IFDEF DEBUG}
180 176 WriteLn('cycle:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
181 177 {$ENDIF}
182   -
183   -
184   - //P := FExperiment.PlayerFromID[Self.ID];
185   - LConsequences := FExperiment.ConsequenceStringFromChoices;
186   - LCount := WordCount(LConsequences,['+']);
187   - if LCount > 0 then
188   - for i := 1 to LCount do
189   - FZMQActor.SendMessage([K_CYCLES,ExtractDelimited(i,LConsequences,['+'])]); // as string generates the pts result
190 178 end;
191 179  
192 180 procedure TGameControl.NextLineage(Sender: TObject);
... ... @@ -229,7 +217,7 @@ end;
229 217 procedure TGameControl.StartExperiment;
230 218 begin
231 219 // all players arrived, lets begin
232   - FExperiment.State:=xsRunning;
  220 + FExperiment.Play;
233 221  
234 222 // wait some time, we just sent a message earlier
235 223 Sleep(5);
... ... @@ -445,6 +433,21 @@ begin
445 433 FormMatrixGame.Timer.Enabled:=True;
446 434 end;
447 435  
  436 +procedure TGameControl.ShowConsequenceMessage(AID, S: string; ForGroup: Boolean);
  437 +var
  438 + LConsequence : TConsequence;
  439 +begin
  440 + LConsequence := TConsequence.Create(nil,S);
  441 + LConsequence.GenerateMessage(ForGroup);
  442 + LConsequence.PresentMessage;
  443 + if ForGroup then
  444 + LConsequence.PresentPoints
  445 + else
  446 + if Self.ID = AID then
  447 + LConsequence.PresentPoints;
  448 +
  449 +end;
  450 +
448 451 procedure TGameControl.DisableConfirmationButton;
449 452 begin
450 453 FormMatrixGame.StringGridMatrix.Enabled:= False;
... ... @@ -467,7 +470,7 @@ begin
467 470 CleanMatrix(AEnabled);
468 471 end;
469 472  
470   -constructor TGameControl.Create(AOwner: TComponent);
  473 +constructor TGameControl.Create(AOwner: TComponent;AppPath:string);
471 474 begin
472 475 FZMQActor := TZMQActor(AOwner);
473 476 inherited Create(FZMQActor.Owner);
... ... @@ -487,8 +490,11 @@ begin
487 490 RowBase:= 0;
488 491 MustDrawDots:=False;
489 492 MustDrawDotsClear:=False;
490   -
491   - FExperiment := TExperiment.Create(FZMQActor.Owner);
  493 + case FActor of
  494 + gaAdmin:FExperiment := TExperiment.Create(FZMQActor.Owner,AppPath);
  495 + gaPlayer:FExperiment := TExperiment.Create(FZMQActor.Owner);
  496 + gaWatcher:FExperiment := TExperiment.Create(FZMQActor.Owner);
  497 + end;
492 498 FExperiment.State:=xsWaiting;
493 499 FExperiment.OnEndTurn := @NextTurn;
494 500 FExperiment.OnEndCycle := @NextCycle;
... ... @@ -633,8 +639,21 @@ procedure TGameControl.ReceiveMessage(AMessage: TStringList);
633 639 end;
634 640 end;
635 641  
  642 + procedure ShowQuestion;
  643 + begin
  644 + case FActor of
  645 + gaPlayer:FZMQActor.Request([
  646 + FZMQActor.ID
  647 + , ' '
  648 + , GA_PLAYER+K_QUESTION
  649 + , AskQuestion(AMessage[1])
  650 + ]);
  651 + end;
  652 + end;
  653 +
636 654 procedure ReceiveChoice;
637   - var P : TPlayer;
  655 + var
  656 + P : TPlayer;
638 657 begin
639 658 P := FExperiment.PlayerFromID[AMessage[1]];
640 659  
... ... @@ -648,6 +667,8 @@ procedure TGameControl.ReceiveMessage(AMessage: TStringList);
648 667  
649 668 case FActor of
650 669 gaPlayer:begin
  670 +
  671 + // last turn// end cycle
651 672 if P.Turn = FExperiment.PlayersCount-1 then
652 673 begin
653 674 // update next turn
... ... @@ -657,16 +678,20 @@ procedure TGameControl.ReceiveMessage(AMessage: TStringList);
657 678 FExperiment.Player[Self.ID] := P;
658 679 end;
659 680  
660   - //CleanMatrix;
661 681 CleanMatrix(False);
662 682  
  683 +
663 684 // no wait turns
664   - EnablePlayerMatrix(Self.ID,0, True);
  685 + // if should continue then
  686 + //if StrToBool(AMessage[6]) then
  687 + //EnablePlayerMatrix(Self.ID,0, True)
  688 +
665 689  
666 690 // wait for server
667 691 Exit;
668 692 end;
669 693  
  694 + // else
670 695 if Self.ID = P.ID then
671 696 begin
672 697 // update confirmation button
... ... @@ -697,20 +722,21 @@ procedure TGameControl.ReceiveMessage(AMessage: TStringList);
697 722 end;
698 723 end;
699 724  
700   - procedure OnEndCycle;
701   - var
702   - LConsequence : TConsequence;
703   - begin
704   - case FActor of
705   - gaPlayer:
706   - begin
707   - LConsequence := TConsequence.Create(nil,AMessage[1]);
708   - LConsequence.GenerateMessage(True);
709   - LConsequence.PresentPoints;
710   - LConsequence.PresentMessage;
711   - end;
712   - end;
713   - end;
  725 + //procedure OnEndCycle;
  726 + //var
  727 + // LConsequence : TConsequence;
  728 + //begin
  729 + // case FActor of
  730 + // gaPlayer:
  731 + // begin
  732 + // LConsequence := TConsequence.Create(nil,AMessage[1]);
  733 + // LConsequence.GenerateMessage(True);
  734 + //
  735 + // LConsequence.PresentPoints;
  736 + // LConsequence.PresentMessage;
  737 + // end;
  738 + // end;
  739 + //end;
714 740  
715 741 procedure ReceiveChat;
716 742 begin
... ... @@ -736,80 +762,55 @@ procedure TGameControl.ReceiveMessage(AMessage: TStringList);
736 762 end;
737 763 end;
738 764  
739   - procedure ShowQuestion;
  765 + procedure QuestionMessages;
  766 + var
  767 + i : integer;
  768 + MID : string;
740 769 begin
741 770 case FActor of
742   - gaPlayer:FZMQActor.Request([
743   - FZMQActor.ID
744   - , ' '
745   - , GA_PLAYER+K_QUESTION
746   - , AskQuestion(AMessage[1])
747   - ]);
  771 + gaPlayer:begin
  772 + if AMessage.Count > 1 then
  773 + begin
  774 + for i := 1 to AMessage.Count -1 do
  775 + begin
  776 + MID := ExtractDelimited(1,AMessage[i],['+']);
  777 + ShowConsequenceMessage(MID, ExtractDelimited(2,AMessage[i],['+']),MID = 'M');
  778 +
  779 + {$IFDEF DEBUG}
  780 + WriteLn('A Prompt consequence should have shown.');
  781 + {$ENDIF}
  782 + end;
  783 + end;
  784 + EnablePlayerMatrix(Self.ID,0, True);
  785 + WriteLn('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
  786 + end;
748 787 end;
749 788 end;
750   -//
751   -// procedure ResumeActor;
752   -// begin
753   -// case FActor of
754   -// gaPlayer:begin
755   -//
756   -// end;
757   -// gaAdmin:begin
758   -//
759   -// end;
760   -// end;
761   -// end;
762   -
763   -
764   - //procedure QuestionMessages;
765   - //var
766   - // LConsequence : TConsequence;
767   - // i : integer;
768   - // MID : string;
769   - //begin
770   - // case FActor of
771   - // // AMessage[i] :=
772   - // // S + '+' +
773   - // // IntToStr(Pts) +'|'+
774   - // // GetConsequenceStylesString(LCsqStyle) +'|'+
775   - // // ExtractDelimited(3,LConsequence, ['|']) +'|'+
776   - // // ExtractDelimited(4,LConsequence, ['|']) +'|'+
777   - // // ExtractDelimited(5,LConsequence, ['|']);
778   - // gaPlayer:begin
779   - // if AMessage.Count > 1 then
780   - // begin
781   - // for i := 1 to AMessage.Count -1 do
782   - // begin
783   - // MID := ExtractDelimited(1,AMessage[i],['+']);
784   - // if (MID = 'M') or (MID = Self.ID) then
785   - // begin
786   - // LConsequence := TConsequence.Create(FormMatrixGame,ExtractDelimited(2,AMessage[i],['+']));
787   - // //LConsequence.PlayerNicname := P.Nicname;
788   - // ShowPopUp(LConsequence.PointMessage(MID = 'M'));
789   - // while FormMatrixGame.PopupNotifier.Visible do
790   - // Application.ProcessMessages;
  789 +
  790 +
  791 + // procedure ResumeActor;
  792 + // begin
  793 + // case FActor of
  794 + // gaPlayer:begin
791 795 //
792   - // {$IFDEF DEBUG}
793   - // WriteLn('A consequence should have shown.');
794   - // {$ENDIF}
795   - // end;
796   - // end;
797   - // end;
  796 + // end;
  797 + // gaAdmin:begin
  798 + //
  799 + // end;
798 800 // end;
799 801 // end;
800   - //end;
801   -
802 802  
803 803 begin
804 804 if MHas(K_ARRIVED) then ReceiveActor;
805 805 if MHas(K_CHAT_M) then ReceiveChat;
806 806 if MHas(K_CHOICE) then ReceiveChoice;
807   - if MHas(K_MESSAGE) then ShowPopUp(AMessage[1]);
  807 + if MHas(K_MESSAGE) then ShowConsequenceMessage(AMessage[1],AMessage[2],StrToBool(AMessage[3]));
808 808 if MHas(K_KICK) then SayGoodBye;
809 809 if MHas(K_START) then NotifyPlayers;
810   - if MHas(K_CYCLES) then OnEndCycle;
811   - //if MHas(K_QUESTION) then ShowQuestion;
812   - //if MHas(K_QMESSAGE) then QuestionMessages;
  810 + if MHas(K_QUESTION) then ShowQuestion;
  811 + if MHAS(K_RESUME) then EnablePlayerMatrix(Self.ID,0, True);
  812 + //if MHas(K_CYCLES) then OnEndCycle;
  813 + if MHas(K_QMESSAGE) then QuestionMessages;
813 814 end;
814 815  
815 816 // Here FActor is garanted to be a TZMQAdmin
... ... @@ -900,11 +901,14 @@ procedure TGameControl.ReceiveRequest(var ARequest: TStringList);
900 901 end;
901 902  
902 903 procedure ValidateChoice;
903   - var P : TPlayer;
904   - S : string;
  904 + var
  905 + LConsequences : string;
  906 + P : TPlayer;
  907 + S : string;
  908 + LEndCycle : Boolean;
905 909 begin
906 910 {$IFDEF DEBUG}
907   - WriteLn('Count:>>>>>>>>>>>>>>>>>>>>>>>>>>>',FExperiment.Condition[FExperiment.CurrentCondition].Turn.Count, '<', FExperiment.Condition[FExperiment.CurrentCondition].Turn.Value);
  911 + WriteLn('Count:',FExperiment.Condition[FExperiment.CurrentCondition].Turn.Count, '<', FExperiment.Condition[FExperiment.CurrentCondition].Turn.Value);
908 912 {$ENDIF}
909 913 P := FExperiment.PlayerFromID[ARequest[0]];
910 914 P.Choice.Row:= GetRowFromString(ARequest[3]); // row
... ... @@ -919,65 +923,70 @@ procedure TGameControl.ReceiveRequest(var ARequest: TStringList);
919 923  
920 924 if Pos('$NICNAME',S) > 0 then
921 925 S := ReplaceStr(S,'$NICNAME',P.Nicname);
922   - ARequest.Append(S);
923 926  
924 927 // update turn
  928 + LEndCycle:=ShouldEndCycle;
925 929 P.Turn := FExperiment.NextTurn;
926 930 FExperiment.Player[P.ID] := P;
927 931  
928   - // broadcast choice
929   - FZMQActor.SendMessage([K_CHOICE,P.ID,ARequest[3],ARequest[4],IntToStr(P.Turn)]);
930   -
931   - if ShouldEndCycle then
  932 + // append results
  933 + ARequest.Append(IntToStr(P.Turn));
  934 + ARequest.Append(S);
  935 + if LEndCycle then
932 936 begin
933   - while FormMatrixGame.PopupNotifier.Visible do
934   - Application.ProcessMessages;
935   -
936   - //if ShouldAskQuestion then // TODO: prompt only when an odd row was selected
937   - // begin
938   - // P.Turn := 0;
939   - // FZMQActor.SendMessage([K_QUESTION,FExperiment.Condition[FExperiment.CurrentCondition].Prompt.Question]);
940   - // end;
  937 + LConsequences := FExperiment.ConsequenceStringFromChoices;// AsString generates the pts result
  938 + ARequest.Append(LConsequences);
  939 +
  940 + if ShouldAskQuestion then // TODO: prompt only when an odd row was selected
  941 + ARequest.Append(FExperiment.Condition[FExperiment.CurrentCondition].Prompt.Question)
  942 + else
  943 + FExperiment.Clean;
941 944 end;
942 945 end;
943 946  
944   - //procedure ValidateQuestionResponse;
945   - //var
946   - // P : TPlayer;
947   - // M : array of UTF8string;
948   - // i : integer;
949   - // LPromptConsequences : TStringList;
950   - //begin
951   - // P := FExperiment.PlayerFromID[ARequest[0]];
952   - // ARequest[2] := K_QUESTION+K_ARRIVED;
953   - //
954   - // // append response of each player
955   - // FExperiment.Condition[FExperiment.CurrentCondition].Prompt.AppendResponse(P.ID,ARequest[3]);
956   - //
957   - // // return to experiment and present the prompt consequence, if any
958   - // if FExperiment.Condition[FExperiment.CurrentCondition].Prompt.ResponsesCount = Experiment.PlayersCount then
959   - // begin
960   - // // M setup
961   - //
962   - //
963   - // // generate messages
964   - // LPromptConsequences := FExperiment.Condition[FExperiment.CurrentCondition].Prompt.AsString;
965   - // if LPromptConsequences.Count > 0 then
966   - // begin
967   - // SetLength(M, 1+LPromptConsequences.Count);
968   - // M[0] := GA_ADMIN+K_QUESTION+K_QMESSAGE;
969   - // for i := 0 to LPromptConsequences.Count -1 do
970   - // M[i+1] := LPromptConsequences[i]
971   - // end;
972   - //
973   - // // send identified messages; each player takes only its own message and ignore the rest
974   - // FZMQActor.SendMessage(M);
975   - // end;
976   - //end;
  947 + procedure ValidateQuestionResponse;
  948 + var
  949 + P : TPlayer;
  950 + M : array of UTF8string;
  951 + i : integer;
  952 + LPromptConsequences : TStringList;
  953 + begin
  954 + P := FExperiment.PlayerFromID[ARequest[0]];
  955 + ARequest[2] := K_QUESTION+K_ARRIVED;
  956 +
  957 + // append response of each player
  958 + FExperiment.Condition[FExperiment.CurrentCondition].Prompt.AppendResponse(P.ID,ARequest[3]);
  959 +
  960 + // return to experiment and present the prompt consequence, if any
  961 + if FExperiment.Condition[FExperiment.CurrentCondition].Prompt.ResponsesCount = FExperiment.PlayersCount then
  962 + begin
  963 +
  964 + // generate messages
  965 + LPromptConsequences := FExperiment.Condition[FExperiment.CurrentCondition].Prompt.AsString;
  966 + SetLength(M, 1+LPromptConsequences.Count);
  967 + M[0] := K_QMESSAGE;
  968 + if LPromptConsequences.Count > 0 then
  969 + begin
  970 + for i := 0 to LPromptConsequences.Count-1 do
  971 + if Pos('$NICNAME',LPromptConsequences[i]) > 0 then
  972 + begin
  973 + P := FExperiment.PlayerFromID[ExtractDelimited(1,LPromptConsequences[i],['+'])];
  974 + LPromptConsequences[i] := ReplaceStr(LPromptConsequences[i],'$NICNAME', P.Nicname);
  975 + end;
  976 + for i := 0 to LPromptConsequences.Count -1 do
  977 + M[i+1] := LPromptConsequences[i];
  978 + end
  979 + else;
  980 +
  981 + // send identified messages; each player takes only its own message and ignore the rest
  982 + FZMQActor.SendMessage(M);
  983 + FExperiment.Clean;
  984 + end;
  985 + end;
977 986 begin
978 987 if MHas(K_LOGIN) then ReplyLoginRequest;
979 988 if MHas(K_CHOICE) then ValidateChoice;
980   - //if MHas(K_QUESTION) then ValidateQuestionResponse;
  989 + if MHas(K_QUESTION) then ValidateQuestionResponse;
981 990 end;
982 991  
983 992 // Here FActor is garanted to be a TZMQPlayer, reply by:
... ... @@ -1020,31 +1029,56 @@ procedure TGameControl.ReceiveReply(AReply: TStringList);
1020 1029 LConsequence : TConsequence;
1021 1030 LCount,
1022 1031 i : integer;
1023   - M : string;
1024 1032 //P : TPlayer;
1025 1033 begin
1026 1034 if Self.ID = AReply[0] then
1027 1035 begin
1028 1036 //P := FExperiment.PlayerFromID[Self.ID];
1029   - LCount := WordCount(AReply[5],['+']);
1030 1037 {$IFDEF DEBUG}
1031 1038 WriteLn('LCount:',LCount);
1032 1039 {$ENDIF}
  1040 + FZMQActor.SendMessage([K_CHOICE,AReply[0],AReply[3],AReply[4],AReply[5]]);
  1041 +
  1042 + LCount := WordCount(AReply[6],['+']);
1033 1043 if LCount > 0 then
1034 1044 for i := 1 to LCount do
1035 1045 begin
1036   - LConsequence := TConsequence.Create(nil,ExtractDelimited(i,AReply[5],['+']));
1037   - M := LConsequence.GenerateMessage(False);
  1046 + LConsequence := TConsequence.Create(nil,ExtractDelimited(i,AReply[6],['+']));
  1047 + LConsequence.GenerateMessage(False);
1038 1048 if LConsequence.ShouldPublishMessage then
1039   - FZMQActor.SendMessage([K_MESSAGE,M])
  1049 + FZMQActor.SendMessage([K_MESSAGE,Self.ID,ExtractDelimited(i,AReply[6],['+']),BoolToStr(False)])
1040 1050 else
1041   - LConsequence.PresentMessage;
1042   - LConsequence.PresentPoints;
  1051 + begin
  1052 + LConsequence.PresentMessage;
  1053 + LConsequence.PresentPoints;
  1054 + end;
1043 1055 {$IFDEF DEBUG}
1044 1056 WriteLn('A consequence should have shown.');
1045 1057 {$ENDIF}
  1058 + //Sleep(1000);
1046 1059 end;
1047 1060  
  1061 + if AReply.Count > 7 then
  1062 + begin
  1063 + LCount := WordCount(AReply[7],['+']);
  1064 + if LCount > 0 then
  1065 + for i := 1 to LCount do
  1066 + begin
  1067 + LConsequence := TConsequence.Create(nil,ExtractDelimited(i,AReply[7],['+']));
  1068 + LConsequence.GenerateMessage(True);
  1069 + FZMQActor.SendMessage([K_MESSAGE,'',ExtractDelimited(i,AReply[7],['+']),BoolToStr(True)]);
  1070 +
  1071 + {$IFDEF DEBUG}
  1072 + WriteLn('A metaconsequence should have shown.');
  1073 + {$ENDIF}
  1074 + //Sleep(1000);
  1075 + end;
  1076 +
  1077 + if AReply.Count > 8 then
  1078 + FZMQActor.SendMessage([K_QUESTION,AReply[8]])
  1079 + else
  1080 + FZMQActor.SendMessage([K_RESUME]);
  1081 + end;
1048 1082 end;
1049 1083 end;
1050 1084  
... ... @@ -1053,13 +1087,13 @@ procedure TGameControl.ReceiveReply(AReply: TStringList);
1053 1087 // // wait
1054 1088 //end;
1055 1089  
1056   - procedure ResumePlayer;
1057   - begin
1058   -
1059   - end;
  1090 + //procedure ResumePlayer;
  1091 + //begin
  1092 + //
  1093 + //end;
1060 1094  
1061 1095 begin
1062   - if MHas(K_RESUME+K_ARRIVED) then ResumePlayer;
  1096 + //if MHas(K_RESUME+K_ARRIVED) then ResumePlayer;
1063 1097 if MHas(K_LOGIN+K_ARRIVED) then LoginAccepted;
1064 1098 if MHas(K_CHOICE+K_ARRIVED) then ChoiceValidated;
1065 1099 //if MHas(K_QUESTION+K_ARRIVED) then QuestionValidated;
... ...
units/game_experiment.pas
... ... @@ -30,28 +30,23 @@ type
30 30  
31 31 TExperiment = class(TComponent)
32 32 private
33   - FExperimentStart : Boolean;
34 33 FExperimentAim,
35 34 FExperimentName,
36 35 FFilename,
37   - FResearcher : UTF8string;
38   - FOnConsequence: TNotifyEvent;
39   - FOnInterlocking: TNotifyEvent;
40   - FOnEndTurn: TNotifyEvent;
41   - FOnEndCondition: TNotifyEvent;
42   - FOnEndCycle: TNotifyEvent;
43   - FOnEndExperiment: TNotifyEvent;
44   - FOnEndGeneration: TNotifyEvent;
45   - FMatrixType: TGameMatrixType;
46   - FRegData : TRegData;
  36 + FResearcher : string;
  37 + FExperimentStart : Boolean;
47 38 FGenPlayersAsNeeded : Boolean;
48   - FPlayers : TPlayers;
49   - FCurrentCondition : integer;
50   - FConditions : TConditions;
51 39 FResearcherCanChat: Boolean;
52 40 FResearcherCanPlay: Boolean;
53 41 FSendChatHistoryForNewPlayers: Boolean;
54 42 FShowChat: Boolean;
  43 + FMatrixType: TGameMatrixType;
  44 + private
  45 + FLastReportColNames : string;
  46 + FRegData : TRegData;
  47 + FPlayers : TPlayers;
  48 + FCurrentCondition : integer;
  49 + FConditions : TConditions;
55 50 FState: TExperimentState;
56 51 FTurnsRandom : TStringList;
57 52 function GetCondition(I : Integer): TCondition;
... ... @@ -90,36 +85,50 @@ type
90 85 procedure SetSendChatHistoryForNewPlayers(AValue: Boolean);
91 86 procedure SetState(AValue: TExperimentState);
92 87 private
  88 + FOnConsequence: TNotifyEvent;
  89 + FOnInterlocking: TNotifyEvent;
  90 + FOnEndTurn: TNotifyEvent;
  91 + FOnEndCondition: TNotifyEvent;
  92 + FOnEndCycle: TNotifyEvent;
  93 + FOnEndExperiment: TNotifyEvent;
  94 + FOnEndGeneration: TNotifyEvent;
93 95 procedure Consequence(Sender : TObject);
94 96 procedure Interlocking(Sender : TObject);
  97 + procedure WriteReportHeader;
  98 + procedure WriteReportRowNames;
  99 + procedure WriteReportRow;
95 100 public
96 101 constructor Create(AOwner:TComponent);override;
97   - constructor Create(AFilename: string; AOwner:TComponent); overload;
  102 + constructor Create(AOwner:TComponent; AppPath:string);overload;
  103 + constructor Create(AOwner:TComponent; AFilename, AppPath:string); overload;
98 104 destructor Destroy; override;
99 105 function LoadFromFile(AFilename: string):Boolean;
100 106 function LoadFromGenerator:Boolean;
101   - function AppendCondition : integer; overload;
102   - function AppendCondition(ACondition : TCondition) : integer;overload;
103   - function AppendContingency(ACondition : integer) : integer;overload;
104   - function AppendContingency(ACondition : integer;AContingency : TContingency) : integer;overload;
105   - function AppendPlayer : integer;overload;
106   - function AppendPlayer(APlayer : TPlayer) : integer; overload;
107 107 procedure SaveToFile(AFilename: string); overload;
108 108 procedure SaveToFile; overload;
109 109 procedure Clean;
110 110 procedure Play;
  111 + property ExperimentAim : string read FExperimentAim write FExperimentAim;
  112 + property ExperimentName : string read FExperimentName write FExperimentName;
  113 + property GenPlayersAsNeeded : Boolean read FGenPlayersAsNeeded write FGenPlayersAsNeeded;
111 114 property ResearcherCanPlay : Boolean read FResearcherCanPlay write SetResearcherCanPlay;
112 115 property ResearcherCanChat : Boolean read FResearcherCanChat write SetResearcherCanChat;
113   - property Researcher : UTF8string read FResearcher write FResearcher;
  116 + property Researcher : string read FResearcher write FResearcher;
  117 + property ShowChat : Boolean read FShowChat write FShowChat;
  118 + property SendChatHistoryForNewPlayers : Boolean read FSendChatHistoryForNewPlayers write SetSendChatHistoryForNewPlayers;
  119 + property MatrixType : TGameMatrixType read FMatrixType write SetMatrixType;
  120 + public
  121 + function AppendCondition : integer; overload;
  122 + function AppendCondition(ACondition : TCondition) : integer;overload;
  123 + function AppendContingency(ACondition : integer) : integer;overload;
  124 + function AppendContingency(ACondition : integer;AContingency : TContingency) : integer;overload;
  125 + function AppendPlayer : integer;overload;
  126 + function AppendPlayer(APlayer : TPlayer) : integer; overload;
114 127 property Condition[I : Integer]: TCondition read GetCondition write SetCondition;
115 128 property ConditionsCount : integer read GetConditionsCount;
116 129 property CurrentCondition : integer read FCurrentCondition write FCurrentCondition;
117 130 property Contingency[C, I : integer] : TContingency read GetContingency write SetContingency;
118 131 property ContingenciesCount[C:integer]:integer read GetContingenciesCount;
119   - property ExperimentAim : UTF8string read FExperimentAim write FExperimentAim;
120   - property ExperimentName : UTF8string read FExperimentName write FExperimentName;
121   - property GenPlayersAsNeeded : Boolean read FGenPlayersAsNeeded write FGenPlayersAsNeeded;
122   - property InterlockingsIn[i:integer]:integer read GetInterlockingsIn;
123 132 property Player[I : integer] : TPlayer read GetPlayer write SetPlayer;
124 133 property PlayerFromID[S : UTF8string ] : TPlayer read GetPlayer write SetPlayer;
125 134 property PlayersCount : integer read GetPlayersCount;
... ... @@ -127,11 +136,10 @@ type
127 136 property PlayerIndexFromID[s : UTF8string]: integer read GetPlayerIndexFromID;
128 137 property PlayerAsString[P:TPlayer]: UTF8string read AliasPlayerAsString;
129 138 property PlayerFromString[s : UTF8string]: TPlayer read AliasPlayerFromString;
  139 + public
  140 + property InterlockingsIn[i:integer]:integer read GetInterlockingsIn;
130 141 property ConsequenceStringFromChoice[P:Tplayer]:UTF8String read GetConsequenceStringFromChoice;
131 142 property ConsequenceStringFromChoices: UTF8String read GetConsequenceStringFromChoices;
132   - property ShowChat : Boolean read FShowChat write FShowChat;
133   - property SendChatHistoryForNewPlayers : Boolean read FSendChatHistoryForNewPlayers write SetSendChatHistoryForNewPlayers;
134   - property MatrixType : TGameMatrixType read FMatrixType write SetMatrixType;
135 143 property NextTurnPlayerID : UTF8string read GetNextTurnPlayerID;
136 144 property NextTurn : integer read GetNextTurn;
137 145 property NextCycle : integer read GetNextCycle;
... ... @@ -143,7 +151,6 @@ type
143 151 property OnEndGeneration : TNotifyEvent read FOnEndGeneration write SetOnEndGeneration;
144 152 property OnEndCondition : TNotifyEvent read FOnEndCondition write SetOnEndCondition;
145 153 property OnEndExperiment : TNotifyEvent read FOnEndExperiment write SetOnEndExperiment;
146   - public
147 154 property OnConsequence : TNotifyEvent read FOnConsequence write SetOnConsequence;
148 155 property OnInterlocking : TNotifyEvent read FOnInterlocking write SetOnInterlocking;
149 156 end;
... ... @@ -489,6 +496,96 @@ begin
489 496 if Assigned(FOnInterlocking) then FOnInterlocking(Sender);
490 497 end;
491 498  
  499 +procedure TExperiment.WriteReportHeader;
  500 +var
  501 + LHeader : string;
  502 +begin
  503 + // header
  504 + LHeader := VAL_RESEARCHER+':'+#9+FResearcher + LineEnding +
  505 + VAL_EXPERIMENT+':' + #9 + FExperimentName + LineEnding +
  506 + VAL_BEGIN_TIME+':' + #9 + DateTimeToStr(Date) + #9 + TimeToStr(Time) + LineEnding + LineEnding;
  507 + FRegData.SaveData(LHeader);
  508 + WriteReportRowNames;
  509 +end;
  510 +
  511 +procedure TExperiment.WriteReportRowNames;
  512 +var
  513 + c,j,i: integer;
  514 + LHeader : string;
  515 +begin
  516 + c:= CurrentCondition;
  517 + // column names, line 1
  518 + LHeader := 'Experimento'+#9+#9;
  519 + for i:=0 to Condition[c].Turn.Value-1 do // player's response
  520 + LHeader += 'P'+IntToStr(i+1)+#9+#9;
  521 +
  522 + for i:=0 to ContingenciesCount[c]-1 do
  523 + if not Contingency[c,i].Meta then
  524 + begin
  525 + LHeader += Contingency[c,i].ContingencyName;
  526 + for j:=0 to Condition[c].Turn.Value-1 do
  527 + LHeader += #9;
  528 + end;
  529 +
  530 + LHeader += VAL_INTERLOCKING+'s';
  531 + for i:=0 to ContingenciesCount[c]-1 do
  532 + if Contingency[c,i].Meta then
  533 + LHeader += #9;
  534 +
  535 + LHeader += LineEnding;
  536 +
  537 +
  538 + // column names, line 2
  539 + LHeader += 'Condição'+#9+'Ciclo'+#9;
  540 + for i:=0 to Condition[c].Turn.Value-1 do
  541 + LHeader += 'Linha'+#9+'Cor'+#9;
  542 +
  543 + for i:=0 to ContingenciesCount[c]-1 do
  544 + if not Contingency[c,i].Meta then
  545 + for j:=0 to Condition[c].Turn.Value-1 do
  546 + LHeader += 'P'+IntToStr(j+1)+#9;
  547 +
  548 + for i:=0 to ContingenciesCount[c]-1 do
  549 + if Contingency[c,i].Meta then
  550 + LHeader += Contingency[c,i].ContingencyName+#9;
  551 + LHeader += LineEnding;
  552 +
  553 + FLastReportColNames := LHeader;
  554 + FRegData.SaveData(LHeader);
  555 +end;
  556 +
  557 +procedure TExperiment.WriteReportRow;
  558 +var
  559 + c,j,i: integer;
  560 + LHeader : string;
  561 +begin
  562 + c:= CurrentCondition;
  563 +
  564 + LHeader := IntToStr(c+1)+#9+IntToStr(Condition[c].Cycles.Count+1)+#9;
  565 + for i:=0 to Condition[c].Turn.Value-1 do
  566 + LHeader += GetRowString(FPlayers[i].Choice.Row)+#9+GetColorString(FPlayers[i].Choice.Color)+#9;
  567 +
  568 + for i:=0 to ContingenciesCount[c]-1 do
  569 + if not Contingency[c,i].Meta then
  570 + for j:=0 to Condition[c].Turn.Value-1 do
  571 + if Contingency[c,i].ConsequenceFromPlayerID(FPlayers[j].ID) <> '' then
  572 + LHeader += '1'+#9
  573 + else
  574 + LHeader += '0'+#9;
  575 +
  576 + for i:=0 to ContingenciesCount[c]-1 do
  577 + if Contingency[c,i].Meta then
  578 + if Contingency[c,i].Fired then
  579 + LHeader += '1'+#9
  580 + else
  581 + LHeader += '0'+#9;
  582 + LHeader += LineEnding;
  583 +
  584 + FLastReportColNames := LHeader;
  585 + FRegData.SaveData(LHeader);
  586 +
  587 +end;
  588 +
492 589 constructor TExperiment.Create(AOwner: TComponent);
493 590 begin
494 591 inherited Create(AOwner);
... ... @@ -497,7 +594,17 @@ begin
497 594 CheckNeedForRandomTurns;
498 595 end;
499 596  
500   -constructor TExperiment.Create(AFilename: string;AOwner:TComponent);
  597 +constructor TExperiment.Create(AOwner: TComponent;AppPath:string);
  598 +begin
  599 + inherited Create(AOwner);
  600 + FTurnsRandom := TStringList.Create;
  601 + LoadExperimentFromResource(Self);
  602 + CheckNeedForRandomTurns;
  603 + FRegData := TRegData.Create(Self, AppPath+VAL_RESEARCHER+'es'+PathDelim+Researcher+PathDelim+ExperimentName+PathDelim+'000.dat');
  604 + WriteReportHeader;
  605 +end;
  606 +
  607 +constructor TExperiment.Create(AOwner:TComponent;AFilename,AppPath:string);
501 608 begin
502 609 inherited Create(AOwner);
503 610 FTurnsRandom := TStringList.Create;
... ... @@ -583,13 +690,31 @@ begin
583 690 end;
584 691  
585 692 procedure TExperiment.Clean;
  693 +var c,i : integer;
586 694 begin
  695 + WriteReportRow;
  696 + for i := 0 to PlayersCount -1 do
  697 + begin
  698 + FPlayers[i].Choice.Row:=grNone;
  699 + FPlayers[i].Choice.Color:=gcNone;
  700 + end;
  701 + c := CurrentCondition;
  702 + for i := 0 to ContingenciesCount[c]-1 do
  703 + Contingency[c,i].Clean;
  704 +
  705 + Condition[c].Prompt.Clean;
587 706  
  707 + FRegData.CloseAndOpen;
588 708 end;
589 709  
590 710 procedure TExperiment.Play;
  711 +var i : integer;
591 712 begin
592   -
  713 + for i := 0 to Condition[CurrentCondition].Turn.Value-1 do
  714 + begin
  715 + //TRegData.Save Header;
  716 + end;
  717 + FState:=xsRunning;
593 718 end;
594 719  
595 720 end.
... ...
units/game_file_methods.pas
... ... @@ -76,7 +76,7 @@ begin
76 76 ResearcherCanPlay:=False;
77 77 ResearcherCanChat:=True;
78 78 SendChatHistoryForNewPlayers:=True;
79   - ExperimentName:='Test Experiment';
  79 + ExperimentName:='test_experiment';
80 80 ExperimentAim:='This is a test experiment.';
81 81 GenPlayersAsNeeded:=True;
82 82 CurrentCondition := 0;
... ... @@ -98,12 +98,16 @@ begin
98 98 SetLength(Contingencies, 4);
99 99 LConcequence := TConsequence.Create(AExperiment,1,[gscPoints, gscB, gscMessage,gscBroadcastMessage],['$NICNAME','queijo','queijos']);
100 100 Contingencies[0] := TContingency.Create(AExperiment,LConcequence,LCriteria1,False);
  101 + Contingencies[0].ContingencyName := 'CRF 1B';
101 102 LConcequence := TConsequence.Create(AExperiment,3,[gscPoints, gscA, gscMessage,gscBroadcastMessage],['$NICNAME','pão','pães']);
102 103 Contingencies[1] := TContingency.Create(AExperiment,LConcequence,LCriteria2,False);
  104 + Contingencies[1].ContingencyName := 'CRF 1A';
103 105 LConcequence := TConsequence.Create(AExperiment,1,[gscPoints, gscG, gscMessage],['','item escolar','itens escolares']);
104 106 Contingencies[2] := TContingency.Create(AExperiment,LConcequence,LCriteria3,True);
  107 + Contingencies[2].ContingencyName := 'MCRF 1G';
105 108 LConcequence := TConsequence.Create(AExperiment,-1,[gscPoints, gscG, gscMessage],['','item escolar','itens escolares']);
106 109 Contingencies[3] := TContingency.Create(AExperiment,LConcequence,LCriteria4,True);
  110 + Contingencies[3].ContingencyName := 'MPUN -1G';
107 111  
108 112 Prompt := TPrompt.Create(
109 113 AExperiment
... ... @@ -129,57 +133,6 @@ var
129 133 // if not (APath[Length(APath)] = PathDelim) then APath:= APath + PathDelim;
130 134 //end;
131 135  
132   - function GetEndCriteria(S:string) : TEndConditionCriterium;
133   - begin
134   - case StrToIntDef(ExtractDelimited(1,S,[',']),2) of
135   - 0: Result.Value := gecAbsoluteCycles;
136   - 1: Result.Value := gecInterlockingPorcentage;
137   - 2: Result.Value := gecWhichComeFirst;
138   - end;
139   - Result.AbsoluteCycles := StrToIntDef(ExtractDelimited(2,S,[',']), 20);
140   - Result.InterlockingPorcentage := StrToIntDef(ExtractDelimited(3,S,[',']),10);
141   - Result.LastCycles := StrToIntDef(ExtractDelimited(4,S,[',']), 10);
142   - end;
143   -
144   - function GetPoints(S: string) : TPoints;
145   - begin
146   - Result.A := StrToIntDef(ExtractDelimited(1,S,[',']),0);
147   - Result.B := StrToIntDef(ExtractDelimited(2,S,[',']),0);
148   - Result.G := StrToIntDef(ExtractDelimited(3,S,[',']),0);
149   - end;
150   -
151   -
152   - function GetChoiceFromString(S:string) : TPlayerChoice;
153   - begin
154   - Result.Row := GetRowFromString(ExtractDelimited(1,S,[',']));
155   - Result.Color := GetGameColorFromString(ExtractDelimited(2,S,[',']));
156   - end;
157   -
158   - function GetPPointsFromString(S:string) : TPlayerPoints;
159   - begin
160   - Result.A := StrToIntDef(ExtractDelimited(1,S,[',']),0);
161   - Result.B := StrToIntDef(ExtractDelimited(2,S,[',']),0);
162   - end;
163   -
164   - function GetStatusFromString(S : string): TGamePlayerStatus;
165   - begin
166   - case ExtractDelimited(1,S,[',']) of
167   - 'esperando': Result := gpsWaiting;
168   - 'jogou': Result := gpsPlayed;
169   - 'jogando': Result := gpsPlaying;
170   - end;
171   - end;
172   -
173   - function GetPromptStyle(S:string):TPromptStyle;
174   - var
175   - i : integer;
176   - begin
177   - // Yes,All,Metacontingency,RecoverLostPoints,
178   - Result := [];
179   - for i := 1 to 4 do
180   - Result := Result + GetPromptStyleFromString(ExtractDelimited(i,S,[',']));
181   - end;
182   -
183 136 procedure ReadExperiment;
184 137 begin
185 138 // Experiment;
... ... @@ -231,33 +184,6 @@ var
231 184 LConsequence : TConsequence;
232 185 LCriteria:TCriteria;
233 186  
234   - function GetCriteriaFromString(S:string):TCriteria;
235   - var
236   - LS : string;
237   - i,
238   - LCount: integer;
239   - begin
240   - LS := ExtractDelimited(1,S,['|']);
241   - LCount := WordCount(LS,[#0,',']);
242   - Result.Rows := [];
243   - for i := 1 to LCount do
244   - Result.Rows += [GetRowFromString(ExtractDelimited(i,LS,[',']))];
245   -
246   - case ExtractDelimited(2,S,['|'])of
247   - 'NONE':Result.Style:=gtNone;
248   - 'CORES':Result.Style:=gtColorsOnly;
249   - 'E':Result.Style:=gtRowsAndColors;
250   - 'LINHAS':Result.Style:=gtRowsOnly;
251   - 'OU':Result.Style:=gtRowsOrColors;
252   - end;
253   -
254   - LS := ExtractDelimited(3,S,['|']);
255   - LCount := WordCount(LS,[#0,',']);
256   - Result.Colors := [];
257   - for i := 1 to LCount do
258   - Result.Colors += [GetGameColorFromString(ExtractDelimited(i,LS,[',']))];
259   - end;
260   -
261 187 procedure SetLCK(i:integer);
262 188 begin
263 189 if IsMeta then
... ... @@ -304,10 +230,10 @@ var
304 230 {$ENDIF}
305 231 s1 := DEF_END;
306 232 end;
307   - EndCriterium := GetEndCriteria(s1);
  233 + EndCriterium := GetEndCriteriaFromString(s1);
308 234 ConditionName := ReadString(LS,KEY_COND_NAME,LS);
309   - Points.Count := GetPoints(ReadString(LS, KEY_POINTS_COUNT,DEF_POINTS));
310   - Points.OnStart := GetPoints(ReadString(LS, KEY_POINTS_ONSTART,DEF_POINTS));
  235 + Points.Count := GetPointsFromString(ReadString(LS, KEY_POINTS_COUNT,DEF_POINTS));
  236 + Points.OnStart := GetPointsFromString(ReadString(LS, KEY_POINTS_ONSTART,DEF_POINTS));
311 237 Turn.Count:= ReadInteger(LS, KEY_TURN_COUNT,1);
312 238 Turn.Value:= ReadInteger(LS, KEY_TURN_VALUE,2);
313 239 Turn.Random:= ReadBool(LS, KEY_TURN_RANDOM,False);
... ... @@ -322,7 +248,7 @@ var
322 248  
323 249 Prompt := TPrompt.Create(
324 250 AExperiment
325   - , GetPromptStyle(ReadString(LS,KEY_PROMPT_STYLE,'todos,sim,metacontingência,recuperar pontos,'))
  251 + , GetPromptStyleFromString(ReadString(LS,KEY_PROMPT_STYLE,'todos,sim,metacontingência,recuperar pontos,'))
326 252 , Contingencies
327 253 , ReadString(LS,KEY_PROMPT_MESSAGE,DEF_PROMPTMESSAGE)
328 254 );
... ...
units/game_resources.pas
... ... @@ -72,8 +72,12 @@ resourcestring
72 72 KEY_CONSEQUE_MESSAGE_APPENDS = '.Consequência.Mensagem.Sufixo.Singular';
73 73 KEY_CONSEQUE_MESSAGE_APPENDP = '.Consequência.Mensagem.Sufixo.Plural';
74 74  
75   -
  75 + VAL_CONSEQUENCE = 'Cosequência';
76 76 VAL_RESEARCHER = 'Pesquisador';
  77 + VAL_EXPERIMENT = 'Experimento';
  78 + VAL_INTERLOCKING = 'Entrelaçamento';
  79 +
  80 + VAL_BEGIN_TIME = 'Começo';
77 81  
78 82 DEF_END = '2,20,10,10,'; // which come first, 20 cycles | 10% entrelaçamentos in the last 10 cycles
79 83 DEF_POINTS = '0,0,0,';
... ...
units/string_methods.pas
... ... @@ -19,8 +19,6 @@ uses
19 19 , game_resources
20 20 ;
21 21  
22   -function GetAndDelFirstValue(var S: string;Sep:Char=','):string; deprecated 'Use ExtracteDelimited from strutils instead';
23   -
24 22 function GetRowString(ARow : TGameRow) : string;
25 23 function GetRowFromString(S : string):TGameRow;
26 24  
... ... @@ -31,6 +29,7 @@ function GetGameColorFromString(S : string) : TGameColor;
31 29  
32 30 function GetPromptStyleFromString(S : string) : TPromptStyle;
33 31 function GetPromptStyleString(AStyle : TPromptStyle) : string;
  32 +function GetGamePromptStyleFromString(S : string) : TGamePromptStyle;
34 33  
35 34 function GetConsequenceStyleFromString(s : string):TGameConsequenceStyle;
36 35 function GetConsequenceStyleString(AStyle : TGameConsequenceStyle): string;
... ... @@ -42,10 +41,19 @@ function GetCriteriaFromString(S : string) : TCriteria;
42 41 function GetCriteriaStyleString(AStyle: TGameStyle) : string;
43 42  
44 43 function GetStatusString(AStatus : TGamePlayerStatus): string;
  44 +function GetStatusFromString(S : string): TGamePlayerStatus;
  45 +
  46 +function GetPPointsFromString(S:string) : TPlayerPoints;
45 47 function GetPPointsString(APPoints : TPlayerPoints) : string;
46   -function GetChoiceString(AChoice : TPlayerChoice) : string;
  48 +function GetPointsFromString(S: string) : TPoints;
47 49 function GetPointsString(APoints : TPoints) : string;
  50 +
  51 +function GetChoiceString(AChoice : TPlayerChoice) : string;
  52 +function GetChoiceFromString(S:string) : TPlayerChoice;
  53 +
48 54 function GetEndCriteriaString(AEndCriterium:TEndConditionCriterium) : string;
  55 +function GetEndCriteriaFromString(S:string) : TEndConditionCriterium;
  56 +
49 57  
50 58 function GetPlayerFromString(s: string): TPlayer;
51 59 function GetPlayerAsString(P: TPlayer): string;
... ... @@ -54,6 +62,57 @@ implementation
54 62  
55 63 uses strutils;
56 64  
  65 +function GetEndCriteriaFromString(S:string) : TEndConditionCriterium;
  66 +begin
  67 + case StrToIntDef(ExtractDelimited(1,S,[',']),2) of
  68 + 0: Result.Value := gecAbsoluteCycles;
  69 + 1: Result.Value := gecInterlockingPorcentage;
  70 + 2: Result.Value := gecWhichComeFirst;
  71 + end;
  72 + Result.AbsoluteCycles := StrToIntDef(ExtractDelimited(2,S,[',']), 20);
  73 + Result.InterlockingPorcentage := StrToIntDef(ExtractDelimited(3,S,[',']),10);
  74 + Result.LastCycles := StrToIntDef(ExtractDelimited(4,S,[',']), 10);
  75 +end;
  76 +
  77 +function GetPointsFromString(S: string) : TPoints;
  78 +begin
  79 + Result.A := StrToIntDef(ExtractDelimited(1,S,[',']),0);
  80 + Result.B := StrToIntDef(ExtractDelimited(2,S,[',']),0);
  81 + Result.G := StrToIntDef(ExtractDelimited(3,S,[',']),0);
  82 +end;
  83 +
  84 +
  85 +function GetChoiceFromString(S:string) : TPlayerChoice;
  86 +begin
  87 + Result.Row := GetRowFromString(ExtractDelimited(1,S,[',']));
  88 + Result.Color := GetGameColorFromString(ExtractDelimited(2,S,[',']));
  89 +end;
  90 +
  91 +function GetPPointsFromString(S:string) : TPlayerPoints;
  92 +begin
  93 + Result.A := StrToIntDef(ExtractDelimited(1,S,[',']),0);
  94 + Result.B := StrToIntDef(ExtractDelimited(2,S,[',']),0);
  95 +end;
  96 +
  97 +function GetStatusFromString(S : string): TGamePlayerStatus;
  98 +begin
  99 + case ExtractDelimited(1,S,[',']) of
  100 + 'esperando': Result := gpsWaiting;
  101 + 'jogou': Result := gpsPlayed;
  102 + 'jogando': Result := gpsPlaying;
  103 + end;
  104 +end;
  105 +
  106 +function GetPromptStyleFromString(S:string):TPromptStyle;
  107 +var
  108 + i : integer;
  109 +begin
  110 + // Yes,All,Metacontingency,RecoverLostPoints,
  111 + Result := [];
  112 + for i := 1 to 4 do
  113 + Result := Result + [GetGamePromptStyleFromString(ExtractDelimited(i,S,[',']))];
  114 +end;
  115 +
57 116 function GetAndDelFirstValue(var S: string;Sep:Char=','): string;
58 117 begin
59 118 Result := Copy(S, 0, pos(Sep, S)-1);
... ... @@ -128,18 +187,18 @@ begin
128 187 end;
129 188  
130 189  
131   -function GetPromptStyleFromString(S: string): TPromptStyle;
  190 +function GetGamePromptStyleFromString(S: string): TGamePromptStyle;
132 191 begin
133 192 // todos,sim,metacontingência,recuperar pontos,
134 193 case UpperCase(S) of
135 194 //'NENHUM','NONE': Result:=[gsNone];
136   - 'TODOS', 'ALL' : Result:=[gsAll];
137   - 'SIM', 'YES','S','Y': Result:=[gsYes];
138   - 'NÃO','NAO','N' : Result:=[gsNo];
139   - 'CONTINGÊNCIA','CONTINGENCIA','CONTINGENCY','OPERANTE', 'OPERANT': Result:=[gsContingency];
140   - 'METACONTINGÊNCIA','METACONTINGENCIA','METACONTINGENCY','META': Result:=[gsMetacontingency];
141   - 'RECUPERA','RECUPERAR','RECUPERAR PONTOS','RECOVER','RESETAR', 'RESET': Result:=[gsRevertPoints];
142   - 'TIRAR DE A AO INVES DE B','TIRAR DE A AO INVÉS DE B', 'B as A' : Result:=[gsBasA];
  195 + 'TODOS', 'ALL' : Result := gsAll;
  196 + 'SIM', 'YES','S','Y': Result := gsYes;
  197 + 'NÃO','NAO','N' : Result := gsNo;
  198 + 'CONTINGÊNCIA','CONTINGENCIA','CONTINGENCY','OPERANTE', 'OPERANT': Result := gsContingency;
  199 + 'METACONTINGÊNCIA','METACONTINGENCIA','METACONTINGENCY','META': Result := gsMetacontingency;
  200 + 'RECUPERA','RECUPERAR','RECUPERAR PONTOS','RECOVER','RESETAR', 'RESET': Result := gsRevertPoints;
  201 + 'TIRAR DE A AO INVES DE B','TIRAR DE A AO INVÉS DE B', 'B as A' : Result := gsBasA;
143 202 end;
144 203 end;
145 204  
... ... @@ -197,33 +256,31 @@ begin
197 256 Result += '|';
198 257 end;
199 258  
200   -function GetCriteriaFromString(S: string): TCriteria;
  259 +function GetCriteriaFromString(S:string):TCriteria;
201 260 var
202   - s1 : string;
203   - i : integer;
  261 + LS : string;
  262 + i,
  263 + LCount: integer;
204 264 begin
205   - s1 := ExtractDelimited(1,S,['|']);
  265 + LS := ExtractDelimited(1,S,['|']);
  266 + LCount := WordCount(LS,[#0,',']);
206 267 Result.Rows := [];
207   -
208   - for i := 1 to WordCount(s1,[#0,',']) do
209   - if ExtractDelimited(i,s1,[',']) <> '' then
210   - Result.Rows += [GetRowFromString(ExtractDelimited(i,s1,[',']))]
211   - else Break;
212   -
213   - s1 := ExtractDelimited(2,S,['|']);
214   - case UpperCase(s1) of
215   - '','INDIFERENTE', 'NONE' : Result.Style := gtNone;
216   - 'E', 'AND' : Result.Style := gtRowsAndColors;
217   - 'OU', 'OR' : Result.Style := gtRowsOrColors;
218   -
  268 + for i := 1 to LCount do
  269 + Result.Rows += [GetRowFromString(ExtractDelimited(i,LS,[',']))];
  270 +
  271 + case ExtractDelimited(2,S,['|'])of
  272 + 'NONE':Result.Style:=gtNone;
  273 + 'CORES':Result.Style:=gtColorsOnly;
  274 + 'E':Result.Style:=gtRowsAndColors;
  275 + 'LINHAS':Result.Style:=gtRowsOnly;
  276 + 'OU':Result.Style:=gtRowsOrColors;
219 277 end;
220 278  
221   - s1 := ExtractDelimited(3,S,['|']);
  279 + LS := ExtractDelimited(3,S,['|']);
  280 + LCount := WordCount(LS,[#0,',']);
222 281 Result.Colors := [];
223   - for i := 1 to WordCount(s1,[#0,',']) do
224   - if ExtractDelimited(i,s1,[',']) <> '' then
225   - Result.Colors += [GetGameColorFromString(ExtractDelimited(i,s1,[',']))]
226   - else Break;
  282 + for i := 1 to LCount do
  283 + Result.Colors += [GetGameColorFromString(ExtractDelimited(i,LS,[',']))];
227 284 end;
228 285  
229 286 function GetCriteriaStyleString(AStyle: TGameStyle): string;
... ...