2

Good afternoon StackOverflow,

I've just signed up here - I've been using this site for ages, and it seems to always be the site to supply the answer so I decided to be part of things.

Without further ado, here is my question -

I am writing an API for LAN parties that me and a group have monthly to help sort things out on the scorekeeping side. My friend is writing the backend for it, and I'm writing the VB6 frontend. It's been a while since I wrote VB6, and I never wrote it as intensively as the grade of frontend I'm aiming for here.

The premise of the program is this - The backend will write events from the game we're playing to a text file in realtime - Which the frontend reads from in realtime. The part I'd like to enquire about at the moment is this -

I know you can read text files line-by-line in VB6. I want the program to 'listen' (so to speak) for certain buzzwords and use their defined 'Values' to affect variables. Here is a mock example of the kind of file it'll be reading -

******************
LANrealm Match Log
******************

Game:       Call of Duty 4
Game Type:  Team Deathmatch
Date:       01-Jan-2013
Time:       19:00:00
Players:    Tramp
        Roper
        d00b
        Pleb
Score Limit:    150

Event:  Game Start  
Event:  Roper killed Pleb (M4A1) shots=5 Feet=2 Body=2 Head=1 
Event:  Tramp committed suicide (Fall damage)
Event:  Tramp killed d00b (Grenade)
Event:  Pleb said "I'm saying something"
Event:  Pleb teamkilled d00b (G3) shots=3 Feet=0 Body=2 Head=1 
Event:  Game Finished

Winner: Roper

Roper:  Kills=1,Deaths=0,Suicides=0,Teamkills=0
Tramp:  Kills=1,Deaths=0,Suicides=1,Teamkills=0
Pleb:   Kills=0,Deaths=0,Suicides=0,Teamkills=1
d00b:   Kills=0,Deaths=0,Suicides=0,Teamkills=0

Well, I think just by looking at this you can tell what I want the program to pick out of that. It would be a lot easier if I just made it fully comma delimited, but I want to maintain readability of the raw text file. But yeah, just in case you didn't get it, I'd want the program to recognise that 'Roper' had 1 'Kill' and so on and so forth. An example code snippet would be great!

Thanks in advance, guys.

Jose Luis
  • 3,307
  • 3
  • 36
  • 53
N3cRiL
  • 85
  • 2
  • 3
  • 8

3 Answers3

4

Here's a function you could use to load the contents of a file:

Public Function LoadFile(dFile As String) As String

    Dim ff As Integer

    On Error Resume Next

    ff = FreeFile
    Open dFile For Binary As #ff
        LoadFile = Space(LOF(ff))
        Get #ff, , LoadFile
    Close #ff

End Function

Next, you want to split the output of that file. First, you will need to know what type of EOL termination character will be produced by the back-end. Assuming each line ends with a carriage return (13) and a line feed (10), you could use this code to store each line into a string array:

Dim lines() As String
lines = Split(LoadFile("LANrealm.log"), vbCrLf)

Finally, it's a matter of cycling through each line (using a For...Next loop) and look for whatever information you want to extract:

For i = 0 To Ubound(lines)
    ' Add here necessary logic to extract the information.
    ' Each line can be accessed by indexing the array as: lines(i)
Next

Hope this helps you get started...


To test the code:

  • Start VB6 and create a new project. VB6 will create an empty project with one form
  • Double click the form to view it
  • Right click the Toolbox and select "Components"
  • Locate the "Microsoft Common Dialog Control" and select it
  • Click OK
  • Now, drag the "CommonDialog" component from the Toolbox onto the form
  • Double click the form to view its source code
  • Paste the following code

NOTE: Make sure you overwrite any pre-existing code

Option Explicit

Private Sub Form_Load()
    cDlg.DefaultExt = "txt"
    cDlg.Filter = "Text Files|*.txt;*.log"
    cDlg.ShowOpen

    If cDlg.fileName <> "" Then AnalyzeFile .fileName
End Sub

Private Sub AnalyzeFile(fileName As String)
    Dim fileContents As String
    Dim lines() As String
    Dim i As Integer

    fileContents = LoadFile(fileName)
    lines = Split(fileContents, vbCrLf)

    For i = 0 To UBound(lines)
        If InStr(1, lines(i), "event:", vbTextCompare) Then
            MsgBox "Line #" & i & " contains the string 'event'" + vbCrLf + vbCrLf + lines(i)
        End If
    Next
End Sub

Private Function LoadFile(dFile As String) As String
    Dim ff As Integer
    On Error Resume Next

    ff = FreeFile
    Open dFile For Binary As #ff
        LoadFile = Space(LOF(ff))
        Get #ff, , LoadFile
    Close #ff
End Function

Run the program and, when asked to supply a file, select one of the logs that will be generated by the back-end.

In this example, the program will tell you which lines contain "event information", such as "Event: Roper killed Pleb (M4A1) shots=5 Feet=2 Body=2 Head=1".

xfx
  • 1,329
  • 8
  • 18
  • I'm sorry, I don't quite understand... Could you dumb it down for me a bit? I'm weird like that, I don't understand a concept unless I know how I got there. I'm sure it's right, I just don't understand! – N3cRiL Jan 15 '13 at 16:29
  • What exactly is that you don't understand? Have you tried using the code in a VB6 project? The first thing you should try (experiment with) is the `LoadFile` function to see how it can load any text file and return its contents. Then, play with the [Split](http://www.vb6.us/tutorials/vb-string-array-functions-split-join-filter) function to see how it generates an array containing each individual line from the file. – xfx Jan 15 '13 at 16:39
  • It's those functions that I don't understand - You see, I've never used them before, so I have no clue as to their syntax, or how to properly apply them. If you could give me a quick rundown/explanation of what, for example 'split', 'vbCrLf' and 'ubound' are, that'd be great. If I had a clue as to what they are/do, I would have a much better time deciphering the rest. Thanks again! – N3cRiL Jan 15 '13 at 16:43
  • I've just added some instructions on how to test them... give it a try; you'll see it's quite simple. – xfx Jan 15 '13 at 17:01
  • Absolutely ideal. Thank you! – N3cRiL Jan 15 '13 at 17:09
0

One problem I would see doing this in real-time, reading and writing is if two or more computers or apps try to open the same file. This could be a bit of a mess.

  • That's alright, it's only gonna be the server reading/writing from it. – N3cRiL Jan 20 '13 at 21:41
  • Are you having your frontend read the file during play or after? Also you say you want your frontend to react to a event. Can you give a little more details? –  Jan 21 '13 at 12:58
  • It's after, essentially. The frontend won't read in real time, it just reads the file on-query. – N3cRiL Jan 21 '13 at 20:55
  • Oh, Okay sounds a lot easier. –  Jan 22 '13 at 04:01
  • Okay, I've posted a new example that I hope can help you. –  Jan 22 '13 at 05:20
  • Thank you! If you'd like to get a better idea of exactly what I'm doing, I'm fairly certain this screendump of the forms I've prepared will give you a comprehensive rundown of it... [Screenshot](http://img195.imageshack.us/img195/6161/capturetsd.png) . I'm also thinking of ways to let the program differentiate between numbers in variable arrays and the player itself, for example, I'd like 'Pleb' to be variable(4) across the board, I feel as though there's something I can implement to stop the program from mixing up information that applies to another player. – N3cRiL Jan 22 '13 at 08:36
  • I don't want 'Pleb' to display 'Tramp's kills. Basically, on parsing, I want the program to filter out info, e.g. when it reads 'teamkills' the program goes "Ah! The following info needs to go into the 'teamkills' variable', and so on and so forth. Pay no mind to the 'Matches' and 'Events' lists for now, they're gonna be included in a more advanced version of my program. – N3cRiL Jan 22 '13 at 08:39
  • Okay, I'm getting a bit of a better picture. So first, it looks like you want a Unique ID for each player. This is getting a little into the Database world. This could make it a little more difficult. About how many users are you looking to use your program? Also is your program going to be used outside of your network, or is this more for a LAN party? Also so if I looking at this right, you want stats for each game, but also overall. So for example Tramp had played 10 games, so say he made 25 kills all together in those 10 games, but maybe in 2 games he didn't? –  Jan 22 '13 at 09:31
  • Also on your stats selection form, you have three listboxes with buttons on the bottom to open a new window. I would ditch the buttons, and use the OnDoubleClick sub. It make's it look more professional. –  Jan 22 '13 at 09:34
  • Thanks for the tip, I'll give it a try! And I'm actually not sure, I'd like to make it a widely used applications, not just at our LAN Parties, but we play a wide variety of games, and not all of them are as flexible as Call of Duty when it comes to extensions. Ideally, I'd the program to ultimately provide statistics per Player, per Match, and per Event - So I'd like the program to recurse through a folder hierarchy, e.g. to populate the playerlist, it would go into the 'Players' directory, which would contain f.e. pleb.txt, tramp.txt and add them to a list, and populate the arrays – N3cRiL Jan 22 '13 at 09:41
  • behind the scenes, the same would count for the matches, it would recurse through the 'Matches' folder, getting all the filenames and populating the 'Matches' list, and making it a bit more human-readable, for example 'TDM-01012013.txt' would come out as Team Deathmatch, 1st Jan 2013. – N3cRiL Jan 22 '13 at 09:42
  • Okay, so for now we'll just keep it on your own local network. I think what would should do is write a server "watchdog" that checks for new log files. This program will parse each game into a master record of all players. To keep track of each user, and their ID you can create a simple INI file to act as a really simple Database. '[1]' 'Name=Tramp' 'RealName=Bob Smith' Of course you'll have to parse that, and use it in an array. However, your really going to have to look into using a real Database eventually, but that's not that hard at all, and you can even create a recap of a game. –  Jan 22 '13 at 09:56
  • That sounds better than anything I can think of... And to simplify matters (thankfully) 100% of our community uses Hamachi (a VPN if you didn't already know) that lets you mount network shares, and that's kind-of where I'd want the files stored, with read-only permissions. I wouldn't want anybody to 'sync' the files, find out they're just ANSI text files and edit them to make themselves look better. I know the server files will stay the same, but I just don't want screenshots popping up everywhere with doctored results. – N3cRiL Jan 22 '13 at 09:57
  • If your using a VPN you could even run a Database server on there and have your program connect to it. That way it would be more secure as well. A really great a free Database server you can use, is called MySQL. And you use it in your program, you just include on DLL from MySQL. –  Jan 22 '13 at 10:07
  • I already use MySQL heavily at work, so that should work out fine! Can you slap VB6 hard enough to talk to SQL? Edit: I just read your comment again and realised how stupid I just sounded. Sorry. Is VB6 compatible with all current versions of SQL or do I have to go digging for legacy? – N3cRiL Jan 22 '13 at 10:23
  • Also - The backend won't be able to talk to SQL directly, but I think I can import the results automatically with an SSIS if I'm correct? – N3cRiL Jan 22 '13 at 10:25
  • I've only talked to MySQL on my laptop once. Check out this link on Planet Source Code. [PSC]http://planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=48230&lngWId=1 It is a great beginner guide. I'll play around on my machine and get back to you on it. Also I would be more than happy to design your tables. I'm pretty good at coming up with them. –  Jan 22 '13 at 10:27
  • Fantastic! Would you prefer my E-Mail address or to add me on Facebook? I somehow feel as though they're more effective means of conversation than this. – N3cRiL Jan 22 '13 at 10:30
  • rudykingco on facebook, or rudyking@gmail.com –  Jan 22 '13 at 10:41
0

Ok, so if you REALLY want to read your file line by line, I would change your logfile a little different.

******************
LANrealm Match Log
******************

Game:  Call of Duty 4
Game Type:  Team Deathmatch
Date: 01-Jan-2013
Time:1 9:00:00
Players: Tramp, Roper, d00b, Pleb
Score Limit:    150

Event:  Game Start  
Event:  Roper killed Pleb (M4A1) shots=5 Feet=2 Body=2 Head=1 
Event:  Tramp committed suicide (Fall damage)
Event:  Tramp killed d00b (Grenade)
Event:  Pleb said "I'm saying something"
Event:  Pleb teamkilled d00b (G3) shots=3 Feet=0 Body=2 Head=1 
Event:  Game Finished

Winner: Roper

Stat: Roper Kills=1,Deaths=0,Suicides=0,Teamkills=0
Stat: Tramp Kills=1,Deaths=0,Suicides=1,Teamkills=0
Stat: Pleb Kills=0,Deaths=0,Suicides=0,Teamkills=1
Stat: d00b Kills=0,Deaths=0,Suicides=0,Teamkills=0

You can use this to read the file line by line.

   Dim FileNo As Integer
   Dim TempData As String
   Dim TempStr As String
   FileNo = FreeFile
   Open "c:\game.log" For Input As FileNo
      Do
         Line Input #FileNo, TempStr
         TempData = TempData & TempStr or do what ever you want it to do with that line.
         DoEvents
      Loop Until EOF(FileNo)
   Close #FileNo
   MsgBox TempData

However, I would suggest to read the whole file into a string, and then parse out info you want. If you did, you can then pick out info you might want, like name of game etc.....

Try this. Create a new module, and paste this in it.

Public Function ParseData(DataSTR As String, StartSTR As String, EndSTR As String) As String
   Dim Split1
   Dim Split2
   Split1 = Split(DataSTR, StartSTR, , 1)
   Split2 = Split(Split1(1), EndSTR, , 1)
   SplitParse = Split2(0)
End Function

Then add this to a command button.

Private Sub Command2_Click()
 Dim FileNo As Integer
   Dim TempData As String
   FileNo = FreeFile
   Open "c:\game.log" For Input As FileNo
      TempData = Input(LOF(FileNo), FileNo)
   Close
   MsgBox TempData
   MsgBox Trim(ParseData(TempData, "Game:", Chr(10)))
End Sub

Now this is just a sample of what you can do.