?
Solved

VB.NET Very custom for each statement

Posted on 2011-10-29
28
Medium Priority
?
216 Views
Last Modified: 2012-05-12
Hi there. I need to make a very custom for each statement.

As the source of information I'm using a console file of the game.

Now in that file it says SOMEPLAYER has selected a hero.

Now I need to find a players name who selected a hero. What hero is not important.
There are 10 players all together. So foreach loop has to loop through the file and search for "has selected" then it should only filter the part with the nick name and go to the next "has selected" line.

Another thing is that if player played more than one game, the program will also take 10 players from last game. To fix that I think when for each statement took first 10 player names it should store the text up to the line where he picked the last player name and then when the statement reads the log file again it should ignore all previous lines.

Same thing applies if player played 3 or 5 games in a row. I hope it is clear what I need to do.

Here is how the console writes hero selection string.

 
Line 10567: ^479[ZRG]Rutsuko^* has selected a hero.
 Line 10579: ^132Love_Him^* has selected a hero.
 Line 10594: ^521Zit0un^* has selected a hero.
 Line 10621: ^187[GEN]Rejanu^* has selected ^885Zephyr^*.
 Line 10674: ^507[GEN]Kenchik^* has selected ^885Magmus^*.
 Line 10688: ^990[2xP]SCOTU^* has selected ^885Plague Rider^*.
 Line 10700: ^950[2xP]Analcucumber^* has selected ^885Thunderbringer^*.
 Line 10702: ^029[GREM]PapaLoko^* has selected ^885Moon Queen^*.
 Line 10703: ^836[ImwS]NightyD^* has selected a hero.
 Line 10704: ^555[HUGR]Mariop4rty^* has selected a hero.

 Line 70163: ^029[GEN]Rejanu^* has selected ^885Night Hound^*.
 Line 70186: ^836[GEN]Kenchik^* has selected ^885Witch Slayer^*.

Open in new window


As you can see there are 12 lines. 10 from one game and 2 from another so it's not always 10 people in the game.... so for each statement must loop until the last "has selected" and count that as the end point. then remember it and ignore everything up to that point next time he searches through the file.
0
Comment
Question by:AlexeyTimofeev
  • 16
  • 6
  • 5
  • +1
28 Comments
 

Author Comment

by:AlexeyTimofeev
ID: 37049668
Another way would be this:

Let's say I've started first game. Console file is clean. Everyone picked heroes, and game started.

For each statement takes every "has selected" line and filters player names and stores them into the listview table or any table. For each statement remembers what line was the last "has selected" (let's say LINE 11704" and stores it into some variable. Then when it  searches for next "has selected" it starts from the line 11704 to ignore the players from last game.
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 37049690
do you really need to use a for each loop? Can LINQ do? What version of .NET do you want this in?
0
 

Author Comment

by:AlexeyTimofeev
ID: 37049764
I'd rather use .NET 2.0. As far as I know LINQ is .NET 4
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:AlexeyTimofeev
ID: 37049767
But if it's easier for you guys I will stick to .NET 4
0
 
LVL 83

Expert Comment

by:CodeCruiser
ID: 37050142
You can read the lines into an array and then save the index of last read and start from that index everytime

Dim MyLine As String() = GetLines() 'A dummy function to populate lines.

For i As Integer = LastIndex to MyLines.Count - 1
  ...
  LastIndex = i 'This will be the starting point next time.
Next
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 37050158
OK, here's the linq code suggestion. I have assumed that you have read the file into a string array (mStr). The code should be self explanatory though I have annotated it a bit.
Dim mStr As String() = {"Line 10567: ^479[ZRG]Rutsuko^* has selected a hero.",
        "Line 10579: ^132Love_Him^* has selected a hero.",
        "Line 10594: ^521Zit0un^* has selected a hero.",
        "Line 10621: ^187[GEN]Rejanu^* has selected ^885Zephyr^*.",
        "Line 10674: ^507[GEN]Kenchik^* has selected ^885Magmus^*.",
        "Line 10688: ^990[2xP]SCOTU^* has selected ^885Plague Rider^*.",
        "Line 10700: ^950[2xP]Analcucumber^* has selected ^885Thunderbringer^*.",
        "Line 10702: ^029[GREM]PapaLoko^* has selected ^885Moon Queen^*.",
        "Line 10703: ^836[ImwS]NightyD^* has selected a hero.",
        "Line 10704: ^555[HUGR]Mariop4rty^* has selected a hero.",
        "Line 70163: ^029[GEN]Rejanu^* has selected ^885Night Hound^*.",
        "Line 70186: ^836[GEN]Kenchik^* has selected ^885Witch Slayer^*."}
'the first pass
Dim Query = From j In mStr Where Not j.Contains("a hero") Select j
'this puts all the selected players into a list
Dim SelectedPlayers = (From s In Query Select s.Split(" ").Last).ToList
'the this gets the highest line number
Dim HighestNumber = (From q In Query Select CInt(q.Split(" ")(1).Replace(":", String.Empty))).Last

Open in new window

0
 
LVL 17

Expert Comment

by:nepaluz
ID: 37050217
the list of selected players (and selectors?) should be either of the two below
Dim SelectedPlayers = (From s In Query Select s.Split("^")(s.Split("^").Count - 2)).ToList
Dim TheSelectors = (From s In Query Select s.Split("^")(1)).ToList

Open in new window

0
 

Author Comment

by:AlexeyTimofeev
ID: 37050444
and how do I get out whatever is in the .tolist?
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 37050499
would you prefer .ToArray? The items are in the list ready for you to put to your table ....
0
 

Author Comment

by:AlexeyTimofeev
ID: 37050503
Could you please provide me with the code of how to insert data into the table.
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 37050510
what would you like to copy to the table? and whatdoes your table look like?
0
 

Author Comment

by:AlexeyTimofeev
ID: 37050535
I have datagridview with 1 field called PLAYERNAME. So I need only the name of players.

Actually I would prefer to have that information in a string format. Let's say GAME1 and then player names separated by comma. GAME2 player names etc...
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 37050548
I'll stick with your initial request. Here goes
Dim TheSelectors = (From s In Query Select s.Split("^")(1)).ToList
Dim PlayerTable As New DataTable("Selected Players")
PlayerTable.Columns.Add(New DataColumn With {.DataType = GetType(System.String), .ColumnName = "Players"})
Dim PlayerRow As DataRow = Nothing
For Each x In TheSelectors
    PlayerRow = PlayerTable.NewRow()
    PlayerRow.ItemArray = {x}
    PlayerTable.Rows.Add(PlayerRow)
Next
'here you can bind the table to the datagridview, e.g
DataGridView1.DataSource = PlayerTable

Open in new window

0
 
LVL 7

Expert Comment

by:vbigham
ID: 37050664
Along the lines of what CodeCruiser is suggesting.  You could loop through and keep track of the last index or "Line" (assuming that it is actually in the file right?).  Here is a regular expression based solution that might work for you. (This is .net 2.0 code, written with vs2010)

My test code:
 
Imports System.Text.RegularExpressions


Module Module1

    Private lastLineNo As Integer

    Sub Main()
        Dim strRegex As String = "^(?:Line\s+)(?<LineNo>\d+):\s+\^(?<PlayerName>[\w\[\]]+)\^\*\s+(?=(?:has selected a hero.))"
        Dim myRegexOptions As RegexOptions = RegexOptions.IgnoreCase Or RegexOptions.Multiline
        Dim myRegex As New Regex(strRegex, myRegexOptions)
        Dim strTargetString As String = IO.File.ReadAllText("C:\console.txt")
        Dim lineNo As Integer

        Dim currentPlayerNames As New List(Of String)

        For Each myMatch As Match In myRegex.Matches(strTargetString)
            If myMatch.Success Then
                If Integer.TryParse(myMatch.Groups("LineNo").Value, lineNo) AndAlso lineNo > lastLineNo Then
                    lastLineNo = lineNo
                    currentPlayerNames.Add(myMatch.Groups("PlayerName").Value)
                End If
            End If
        Next

        Dim dt As New Data.DataTable
        dt.Columns.Add("PlayerName")

        If currentPlayerNames.Count > 0 Then
            For Each plName In currentPlayerNames
                dt.Rows.Add(plName)
            Next
        End If
    End Sub

End Module

Open in new window


And the file contents of C:\console.txt:
 console.txt
0
 

Author Comment

by:AlexeyTimofeev
ID: 37050804
Line numbers are not in the console log file... I added them up myself.
0
 
LVL 7

Accepted Solution

by:
vbigham earned 2000 total points
ID: 37051025
Maybe this is closer to what you need?
Module Module1

    ' Simulate last remembered index '
    Private lastIndex As Integer = 7


    Sub Main()
        Dim strRegex As String = "^\s*\^\d+(?<PlayerName>[\w\[\]]+)\^\*\s+(?=has selected)"
        Dim myRegexOptions As RegexOptions = RegexOptions.IgnoreCase Or RegexOptions.Multiline
        Dim myRegex As New Regex(strRegex, myRegexOptions)
        Dim targetLines() As String = IO.File.ReadAllLines("C:\console.txt")

        Dim currentPlayerNames As New List(Of String)

        For i As Integer = lastIndex To targetLines.Length - 1
            lastIndex = i

            Dim myMatch As Match = myRegex.Match(targetLines(i))

            If myMatch.Success Then
                currentPlayerNames.Add(myMatch.Groups("PlayerName").Value)
            End If
        Next

        Dim dt As New Data.DataTable
        dt.Columns.Add("PlayerName")

        If currentPlayerNames.Count > 0 Then
            For Each plName In currentPlayerNames
                dt.Rows.Add(plName)
            Next
        End If
    End Sub

End Module

Open in new window


it should only filter the part with the nick name
I'm not sure what exactly that means, but this one should grab:
[ZRG]Rutsuko    from    ^479[ZRG]Rutsuko^*
and
Love_Him    from    ^132Love_Him^*
0
 

Author Comment

by:AlexeyTimofeev
ID: 37052739
^479 and ^132 are the color codes. I don't need them, however I don't need the clan tag also that is inside " [] ". Let's say [ZRG]. Could you fix that too please.
0
 

Author Comment

by:AlexeyTimofeev
ID: 37052744
I also forgot to mention that the console.log file is usually in use by another application. So I need my application to be able to read it even if the file is in use.
0
 

Author Comment

by:AlexeyTimofeev
ID: 37052745
PS. I do not save any information to the console.log file, I only need to read it.
0
 
LVL 7

Expert Comment

by:vbigham
ID: 37053118
Reading the file shouldn't be a problem for you.  Try this expression to omit the clan tags.

^\s*\^\d+(?(\[).+\]|)(?<PlayerName>[\w]+)\^\*\s+(?=has selected)
0
 

Author Comment

by:AlexeyTimofeev
ID: 37053137
Application crashes if the console.log file is in use by the game. When I close the game it works fine.
0
 
LVL 7

Expert Comment

by:vbigham
ID: 37053148
what is the exception? and how are you reading it in? IO.File.ReadAllLines?
0
 

Author Comment

by:AlexeyTimofeev
ID: 37053159
The process cannot access the file 'C:\Users\Rejanu\Documents\Heroes of Newerth\
game\console.log' because it is being used by another process.
0
 

Author Comment

by:AlexeyTimofeev
ID: 37053160
I'm using exact code you gave me.
0
 

Author Comment

by:AlexeyTimofeev
ID: 37053162
When this is solved you probably want to have a look at my other question. No one seems to be knowing the answer.

http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_27422160.html#a37053131
0
 
LVL 7

Expert Comment

by:vbigham
ID: 37053183
Can you read it in notepad while playing? The game might have opened it with FileShare.None in which case you won't have access while the game is running..  If it opened it with FileShare.Read, then you should be able to read it while playing.
0
 

Author Comment

by:AlexeyTimofeev
ID: 37053257
I am able to open it with notepad, however my program gives an error.
0
 

Author Comment

by:AlexeyTimofeev
ID: 37054018
Well I sort of found a workaround. I'm copying the file to the temporary location and reading it, then deleting the temporary file. Thanks for help.

Please see if you can help me with this:

http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_27422160.html#a37053131
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
In real business world data are crucial and sometimes data are shared among different information systems. Hence, an agreeable file transfer protocol need to be established.
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses
Course of the Month17 days, 6 hours left to enroll

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question