• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 218
  • Last Modified:

VB.NET Very custom for each statement

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
AlexeyTimofeev
Asked:
AlexeyTimofeev
  • 16
  • 6
  • 5
  • +1
1 Solution
 
AlexeyTimofeevAuthor Commented:
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
 
nepaluzCommented:
do you really need to use a for each loop? Can LINQ do? What version of .NET do you want this in?
0
 
AlexeyTimofeevAuthor Commented:
I'd rather use .NET 2.0. As far as I know LINQ is .NET 4
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

 
AlexeyTimofeevAuthor Commented:
But if it's easier for you guys I will stick to .NET 4
0
 
CodeCruiserCommented:
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
 
nepaluzCommented:
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
 
nepaluzCommented:
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
 
AlexeyTimofeevAuthor Commented:
and how do I get out whatever is in the .tolist?
0
 
nepaluzCommented:
would you prefer .ToArray? The items are in the list ready for you to put to your table ....
0
 
AlexeyTimofeevAuthor Commented:
Could you please provide me with the code of how to insert data into the table.
0
 
nepaluzCommented:
what would you like to copy to the table? and whatdoes your table look like?
0
 
AlexeyTimofeevAuthor Commented:
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
 
nepaluzCommented:
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
 
vbighamCommented:
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
 
AlexeyTimofeevAuthor Commented:
Line numbers are not in the console log file... I added them up myself.
0
 
vbighamCommented:
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
 
AlexeyTimofeevAuthor Commented:
^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
 
AlexeyTimofeevAuthor Commented:
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
 
AlexeyTimofeevAuthor Commented:
PS. I do not save any information to the console.log file, I only need to read it.
0
 
vbighamCommented:
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
 
AlexeyTimofeevAuthor Commented:
Application crashes if the console.log file is in use by the game. When I close the game it works fine.
0
 
vbighamCommented:
what is the exception? and how are you reading it in? IO.File.ReadAllLines?
0
 
AlexeyTimofeevAuthor Commented:
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
 
AlexeyTimofeevAuthor Commented:
I'm using exact code you gave me.
0
 
AlexeyTimofeevAuthor Commented:
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
 
vbighamCommented:
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
 
AlexeyTimofeevAuthor Commented:
I am able to open it with notepad, however my program gives an error.
0
 
AlexeyTimofeevAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

  • 16
  • 6
  • 5
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now