On Fri, Aug 3, 2012 at 11:02 AM, Jes=FAs Gabriel y Gal=E1n
<jgabrielygalan / gmail.com> wrote:
> On Fri, Aug 3, 2012 at 10:39 AM, b1_ __ <lists / ruby-forum.com> wrote:
>> I am trying to extract information from a po-ker hand history text file
>> as an exercise in learning RegExp and ruby file manipulation classes IO
>> and File.
>>
>> The way the hand history text file is set out is like so:
>>
>> Hand No. xxxx - Date xxxx Time xxxx
>> Game type: xxxx Blinds level: xxxx
>> Table type: xxx
>> Player 1: xxxx (chip count)
>> Player 2: xxxx (chip count)
>> Player 3: xxxx (chip count)
>> Player 4: xxxx (chip count)
>> Hole Cards Phase
>> Player 1 calls
>> Player 2 raise
>> Player 3 folds
>> Flop Phase
>> Player 1 raises
>> Player 2 calls
>> Turn Phase
>> etc
>> etc
>> River Phase
>> etc
>> etc
>> Player 2 wins
>>
>>
>>
>> In my testing I have extracted successfully the very simple statistic of
>> VP$IP, which is the percentage of times a player Voluntarily Puts $ In
>> Pot pre-flop. So this is:
>>
>> Number of time called or raise pre-flop / Number of hands at the table
>>
>> My code (I used what I think is a Finite State Machine?):
>>
>> File.open("test_read.txt") do |f|
>>
>>   count =3D 0
>>   state =3D nil
>>
>>   while (line =3D f.gets)
>>     case (state)
>>     when nil
>>       # Look for the words "Hole Cards" and if found turn on text
>> processing
>>       if (line.match(/Hole Cards/))
>>         state =3D :parsing
>>       end
>>     when :parsing
>>       # Look for word "Flop" or "wins" and if found stop processing text
>>       if (line.match(/Flop/)) || (line.match(/wins/))
>>         state =3D nil
>>       else
>>         if (line.match(/#{name} calls/)) || (line.match(/#{name}
>> raises/)) then count +=3D 1 end
>>       end
>>     end
>>   end
>>
>>   return count
>>
>> end
>>
>> This code processes text only when inside the Hole Card phase (pre-flop
>> phase) between lines with words "Hole Cards" (start text processing) and
>> "Flop" or "wins" (stop processing text). It increments a counter if it
>> finds the words "calls" and "raises" next to a player's name. This code
>> ran through the whole file, maybe over hundreds of hands, and extracted
>> the data.
>>
>> The problem I am having is that I need to have the extracted data
>> associate with hand data. Hand data might be the date of the hand was
>> played, the number of players in the hand, the blind level. This means I
>> need isolate each hand, extract the hand data and put it in a hash for
>> example, then extract stats like VP$IP for each player (a hand-by-hand
>> approach rather than a file-wide approach). So the output might go into
>> a text file specific to each player that would look like:
>>
>> Player 1
>>     VP$IP   2P  3P  4P  All  HandsAtTables
>> 2012-07-23    3  201  21  225  534
>> 2012-07-24    45  10  3  58  1001
>> 2012-07-25     5  5  5  15  420
>>
>> Can I do this without storing data in arrays or objects? I've been
>> thinking I can use another Finite State Machine, only look for the words
>> "Hand" (start of hand) and "wins" (end of hand), the problem is I need
>> some of the data on the line that has the word "Hand" on it, something I
>> can't do with my code above. I also need to switch between hands when
>> there are no lines between the word "wins" and the next line which will
>> have the word "Hands" on it indicating the start of the next hand.
>
> I don't understand the part about not using arrays or objects. If you
> need to accumulate stuff while processing that's the only way.
> It seems that you want to keep separate counts by date and number of
> players. So I would use a hash whose key is a composite of both values
> (a struct with both fields for example), or maybe a hash of hashes.
>
> When you find the "Hand" line, you parse the date and the following
> lines to find out the number of players. With this you get the key to
> the hash. The value will be the count. Then you keep your current
> logic of being before the flop and counting. When you find another
> Hand, you first write the count to the hash with the current key, then
> recompute the next key based on the Hand line and number of players.
> Something like:
>
>
> Key =3D Struct.new :date, :number_of_players
> state =3D nil
> current_key =3D nil
> results =3D Hash.new(0) # keys will return a value of 0 when they don't e=
xist
> while (line =3D f.gets)
>     case (state)
>     when nil
>       if(line.match(/^Hand/)
>         #find the date and the number of players in subsequent lines
>         key =3D Key.new date,number_of_players

There's an error. That should be current_key =3D ...

Jesus.