I'm trying to make a program that takes a text file and parses it into lines and each line is data on a tribe using CSV.
What i'm trying to do is take the top 20 into an array of TTribe based on rank which is the 8th piece of data on each line.
This is my code thus far and so far it keeps giving me EaccessViolations when I run it.
[highlight=pascal]unit StatsTW;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TTribe = record
ID : Integer;
name : String[33];
tag : String[7];
members : Integer;
villages :Integer;
points : Integer;
all_points : Integer;
rank : Integer;
End;
TfrmStatsTW = class(TForm)
btnNewStats: TButton;
btnUpdateStats: TButton;
edtResult: TEdit;
procedure btnUpdateStatsClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmStatsTW: TfrmStatsTW;
implementation
{$R *.dfm}
function Parse(Char, S: string; Count: Integer): string;
var
I: Integer;
T: string;
begin
if S[Length(S)] <> Char then
S := S + Char;
for I := 1 to Count do
begin
T := Copy(S, 0, Pos(Char, S) - 1);
S := Copy(S, Pos(Char, S) + 1, Length(S));
end;
Result := T;
end;
procedure TfrmStatsTW.btnUpdateStatsClick(Sender: TObject);
var
//PrevPost : TextFile;
RawStats : TextFile;
Tribes :String;
TopTribes :Array[1..20] of TTribe;
Count:integer;
row : String;
begin
Count:=1;
AssignFile(RawStats,'ally.txt');
reset(RawStats);
While NOT EOF(RawStats) Do
Begin
Read(RawStats, Tribes);
row:= parse(chr(10),tribes,count);
Count:=Count+1;
if StrToInt(parse(',',row,8)) < 21 then
begin
TopTribes[StrToInt(parse(',',row,8))].ID:=StrToInt(Parse(',',row,1));
TopTribes[StrToInt(parse(',',row,8))].name:=Parse(',',row,2);
TopTribes[StrToInt(parse(',',row,8))].tag:=Parse(',',row,3);
TopTribes[StrToInt(parse(',',row,8))].members:=StrToInt(Parse(',',row,4));
TopTribes[StrToInt(parse(',',row,8))].villages:=StrToInt(Parse(',',row,5));
TopTribes[StrToInt(parse(',',row,8))].points:=StrToInt(Parse(',',row,6));
TopTribes[StrToInt(parse(',',row,8))].all_points:=StrToInt(Parse(',',row,7));
TopTribes[StrToInt(parse(',',row,8))].rank:=StrToInt(Parse(',',row,8));
end;
End;
CloseFile(RawStats);
ShowMessage('hi');
{AssignFile(Prevpost, 'prevpost.txt');
reset(PrevPost);
For count:=1 to 20 do
edtResult.Text:=TopTribes[count].tag + chr(10); }
end;
end.[/highlight]
Last edited by NeoNMD; 09-03-2009 at 01:06 PM.
The segmentation fault may be a result of the data, not the code. Without having both, it will be hard to diagnose.
I thought I had made alot of progress but it appears my parser magically broke on its own somewhere along the way.
[highlight=pascal]unit StatsTW;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TTribe = record
ID : Integer;
name : String[33];
tag : String[12];
members : Integer;
villages :Integer;
points : Integer;
all_points : Integer;
rank : Integer;
VillagePC:real;
MemberPC:real;
PointsPC:real;
VillagePerMember:real;
End;
TfrmStatsTW = class(TForm)
btnNewStats: TButton;
btnUpdateStats: TButton;
edtResult: TEdit;
edtResultPart2: TEdit;
edtResultPart3: TEdit;
edtResultPart4: TEdit;
edtWorld: TEdit;
edtMap: TEdit;
edtPost: TEdit;
procedure btnUpdateStatsClick(Sender: TObject);
procedure VillageStats;
Procedure MakePost;
Procedure ComparePost;
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmStatsTW: TfrmStatsTW;
TopTribes :Array[1..20] of TTribe;
WorldPoints:Integer;
TribeCount:Integer;
implementation
{$R *.dfm}
function OldParse(Char, S: string; Count: Integer): string;
var
I: Integer;
T: string;
begin
if S[Length(S)-1] <> Char[1] then
S := S + Char;
for I := 1 to Count do
begin
T := Copy(S, 0, Pos(Char, S) - 1);
S := Copy(S, Pos(Char, S) + length(char), Length(S));
end;
Result := T;
end;
function Insert(Char, S: string; Count: Integer; InstText: String): string;
var
I: Integer;
T: string;
D: String;
begin
if S[Length(S)-1] <> Char[1] then
S := S + Char;
D:='';
T:='';
for I := 1 to Count do
begin
D := D+Char+T;
T := Copy(S, 0, Pos(Char, S) - 1);
S := Copy(S, Pos(Char, S) + length(char), Length(S));
end;
T:=InstText;
Result:=D+Char+T+Char+S;
end;
function Parse(Char, S: string; Count: Integer): string;
var
I: Integer;
T: string;
begin
if S[Length(S)] <> Char then
S := S + Char;
for I := 1 to Count do
begin
T := Copy(S, 0, Pos(Char, S) - 1);
S := Copy(S, Pos(Char, S) + 1, Length(S));
end;
Result := T;
end;
Procedure TfrmStatsTW.MakePost;
Begin
edtPost.Text:= edtWorld.Text+#10+edtResult.Text+#10+edtResultPart 2.Text+#10+edtResultPart3.text+#10+edtResultPart4. Text+#10+edtMap.text;
End;
Procedure CompareObj(OldObj,CurrentObj:string; Var CurrentLine:String);
Begin
If StrToInt(OldObj) <> StrToInt(CurrentObj) then
If StrToInt(OldObj) < StrToInt(CurrentObj) then
CurrentLine:='.'+CurrentLine
Else
CurrentLine:='.'+CurrentLine;
End;
Procedure TfrmStatsTW.ComparePost;
Var
CurrentPost:String;
LastPost:TextFile;
CurrentSect:String;
CurrentLine:String;
CurrentObj:String;
OldLine:String;
OldObj:String;
Count:integer;
Begin
CurrentPost:=edtPost.text;
AssignFile(LastPost,'lastpost.txt');
Reset(LastPost);
Readln(LastPost,OldLine);
//section1
For Count:=1 to 5 do
Begin
Readln(LastPost,OldLine);
CurrentSect:=OldParse(#10+#10,CurrentPost,1);
CurrentLine:=Parse(#10,CurrentSect,count+1);
OldObj:=Parse(#10,OldLine,1);
CurrentObj:=Parse(#10,CurrentLine,1);
CompareObj(OldObj,CurrentObj,Currentline);
CurrentSect:=Insert(#10,CurrentSect,Count+1,Curren tLine);
CurrentPost:=Insert(#10#10,CurrentPost,1,CurrentSe ct);
End;
//Section2
Readln(LastPost,OldLine);
Readln(LastPost,OldLine);
For Count:=1 to 20 do
Begin
Readln(LastPost,OldLine);
CurrentSect:=OldParse(#10+#10,CurrentPost,2);
CurrentLine:=Parse(#10,CurrentSect,count+1);
OldObj:=Parse(#10,OldLine,2);
CurrentObj:=Parse(#10,CurrentLine,2);
CompareObj(OldObj,CurrentObj,Currentline);
CurrentSect:=Insert(#10,CurrentSect,Count+1,Curren tLine);
CurrentPost:=Insert(#10#10,CurrentPost,2,CurrentSe ct);
End;
//Section3
Readln(LastPost,OldLine);
Readln(LastPost,OldLine);
For Count:=1 to 20 do
Begin
Readln(LastPost,OldLine);
CurrentSect:=OldParse(#10+#10,CurrentPost,3);
CurrentLine:=Parse(#10,CurrentSect,count+1);
OldObj:=Parse(#10,OldLine,2);
CurrentObj:=Parse(#10,CurrentLine,2);
CompareObj(OldObj,CurrentObj,Currentline);
CurrentSect:=Insert(#10,CurrentSect,Count+1,Curren tLine);
CurrentPost:=Insert(#10#10,CurrentPost,4,CurrentSe ct);
End;
End;
Procedure TfrmStatsTW.VillageStats;
Var
count:integer;
WorldVillage:integer;
WorldVillageStr:String;
TopMembers:integer;
TopVillages:integer;
TopPoints:integer;
VillagePcStr:String;
TopVillagesPc:String;
TopPointsPc:String;
pointsPcStr:String;
WorldMembersStr:String;
WorldMembers:Integer;
TopMembersPc:String;
MembersPcStr:String;
VPMPcStr:String;
Begin
InputQuery('Village Query','How many villages are on this world?',WorldVillageStr);
WorldVillage:=StrToInt(WorldVillageStr);
InputQuery('Members Query','How many Members are on this world?',WorldMembersStr);
WorldMembers:=StrToInt(WorldMembersStr);
TopMembers:=0;
TopVillages:=0;
TopPoints:=0;
For Count:=1 to 20 do
begin
TopMembers:=TopMembers + TopTribes[count].members;
TopVillages:=TopVillages + TopTribes[count].villages;
TopPoints:=TopPoints + TopTribes[Count].all_points;
end;
Str((TopVillages/Worldvillage*100):5:3, TopVillagesPC);
edtResult.Text:= 'Village standings Top 20: '+IntToStr(TopVillages)+' Villages - '+ TopVillagesPC +'% of the world.'+#10;
For count:=1 to 20 do
begin
TopTribes[count].VillagePC:=TopTribes[count].villages/WorldVillage*100;
Str(TopTribes[count].VillagePC:5:3,VillagePcStr);
edtResult.Text:=edtResult.Text + TopTribes[count].tag + ': ' + IntToStr(TopTribes[count].villages) + ' villages - ' + VillagePcStr + '%' + #10;
end;
Str((TopPoints/WorldPoints*100):5:3, TopPointsPc);
edtResultPart2.Text:='Points Standings Top 20: '+IntToStr(TopPoints)+' Points - '+ TopPointsPc +'% of the world.'+#10;
For count:=1 to 20 do
begin
TopTribes[count].PointsPC:=TopTribes[count].all_points/WorldPoints*100;
Str(TopTribes[count].PointsPC:5:3,PointsPcStr);
edtResultPart2.Text:=edtResultPart2.text + TopTribes[Count].tag + ': '+ IntToStr(TopTribes[count].all_points)+' points - '+PointsPcStr+'&'+#10;
end;
Str((Topmembers/WorldMembers*100):5:3, TopMembersPc);
edtResultPart3.Text:='Members Standings Top 20: '+IntToStr(TopMembers)+' Members - '+ TopMembersPc +'% of the world.'+#10;
For count:=1 to 20 do
begin
TopTribes[count].MemberPC:=TopTribes[count].members/TopMembers;
Str(TopTribes[count].MemberPC:5:3,MembersPcStr);
edtResultPart3.Text:=edtResultPart3.Text + TopTribes[Count].tag + ': '+ IntToStr(TopTribes[count].members)+' Members - '+MembersPcStr+'&'+#10;
end;
edtResultPart4.text:='Member Powers'+#10;
For count:=1 to 20 do
begin
TopTribes[count].VillagePerMember:=TopTribes[count].villages/TopTribes[count].Members;
Str(TopTribes[count].VillagePerMember:5:3,VPMPcStr);
edtResultPart4.text:=edtResultPart4.text + TopTribes[count].tag + ': '+ VPMPcStr +' Villages per member'+#10;
end;
edtWorld.text:= 'The World'+#10+IntToStr(WorldMembers)+' Players'+#10+IntToStr(WorldVillage)+' Villages'+#10+IntToStr(WorldPoints)+' Points'+#10+IntToStr(TribeCount)+' Tribes';
edtMap.Text:= ''+TopTribes[1].tag+''+#10+''+TopTribes[2].tag+''+#10+''+TopTribes[3].tag+''+#10+''+TopTribes[4].tag+''+#10+''+TopTribes[5].tag+''+#10+
''+TopTribes[6].tag+''+#10+''+TopTribes[7].tag+''+#10+''+TopTribes[8].tag+''+#10+''+TopTribes[9].tag+''+#10+''+TopTribes[10].tag+''+#10+
'maps.twstats.com/map.php?type=map&tribe_0_id='+IntToStr(TopTribes[1].id)+'&tribe_0_colour=FF0000&tribe_1_id='+IntToStr (TopTribes[2].id)+'&tribe_1_colour=FFa800&tribe_2_id='+IntToStr (TopTribes[3].id)+'&tribe_2_colour=E3FF00&tribe_3_id='+IntToStr (TopTribes[4].id)+'&tribe_3_colour=2CFF00&tribe_4_id='+IntToStr (TopTribes[5].id)+'&tribe_4_colour=00FFFF&tribe_5_id='+IntToStr (TopTribes[6].id)+'&tribe_5_colour=00ACFF&tribe_6_id='+IntToStr (TopTribes[7].id)+'&tribe_6_colour=0037FF&tribe_7_id='+IntToStr (TopTribes[8].id)+'&tribe_7_colour=B100FF&tribe_8_id='+IntToStr (TopTribes[9].id)+'&tribe_8_colour=FF00C8&tribe_9_id='+IntToStr (TopTribes[10].id)+'&tribe_9_colour=FFFFFF&zoom=100¢rex=500& centrey=500&nocache=1&fill=333333&grid=1&s=en37';
End;
procedure TfrmStatsTW.btnUpdateStatsClick(Sender: TObject);
var
RawStats : TextFile;
Tribes :String;
Count:Integer;
begin
WorldPoints:=0;
TribeCount:=0;
AssignFile(RawStats,'ally.txt');
reset(RawStats);
ShowMessage('hello again');
for Count:=1 to 20 do
//While NOT EOF(RawStats) Do
begin
Readln(RawStats, Tribes);
TribeCount:=TribeCount+1;
WorldPoints:=WorldPoints+ StrToInt(Parse(',',tribes,7));
//if (StrToInt(parse(',',tribes,8)) < 21) and (StrToInt(parse(',',tribes,8)) > 0) then
begin
ShowMessage('hello again');
TopTribes[StrToInt(parse(',',tribes,8))].ID:=StrToInt(Parse(',',tribes,1));
TopTribes[StrToInt(parse(',',tribes,8))].name:=Parse(',',tribes,2);
TopTribes[StrToInt(parse(',',tribes,8))].tag:=Parse(',',tribes,3);
TopTribes[StrToInt(parse(',',tribes,8))].members:=StrToInt(Parse(',',tribes,4));
TopTribes[StrToInt(parse(',',tribes,8))].villages:=StrToInt(Parse(',',tribes,5));
TopTribes[StrToInt(parse(',',tribes,8))].points:=StrToInt(Parse(',',tribes,6));
TopTribes[StrToInt(parse(',',tribes,8))].all_points:=StrToInt(Parse(',',tribes,7));
TopTribes[StrToInt(parse(',',tribes,8))].rank:=StrToInt(Parse(',',tribes,8));
end;
end;
CloseFile(RawStats);
{ShowMessage('hello again');
//VillageStats;
//MakePost;
//ComparePost;}
end;
end.
[/highlight]
I've commented alot of it out because it WAS working til a minute ago...
Edit:
This is the data:
hxxp://en40.tribalwars.net/map/ally.txt
Last edited by WingedPanther; 09-03-2009 at 12:59 PM. Reason: change PHP tag to highlight=pascal
I used a regex to validate each line:
One line didn't validate:Code:^[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*\,[^\,]*$
Code:12502,BLAH,BLAH,1,1,126,126,3775
Sorry, i've only been programming 6 months. Can you point me in the right direction of the bit that needs changing then?
Thanks for your sharing. Thanks for sharing this useful information. It's great.
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks