Using VB2008 to acccess the Betfair API: A tutorial

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Vadim
    Junior Member
    • Mar 2009
    • 12

    #61
    Mumbles0, thanks!
    What next?

    Comment

    • Dodgee
      Junior Member
      • Jan 2009
      • 17

      #62
      Treeview of events/markets

      Any ideas on how to populate a treeview with the hierarchy of events and markets?

      Eg:

      Code:
      |Horse Racing
             |GB
                   |Aintree Specials
                   |Kemp 25th Mar
                   |Ling 25th Mar
             |IRE
                   |Punchestown Specials
                   |Steward's Enquiry
      I've tried a couple of different ways using loops and string manipulation to extract each folder name from the menupath, but I either end up with the full menupath as a separate node in the tree, e.g:

      Code:
      |Horse Racing
             |\GB\Aintree Specials\Top Jockey
             |\GB\Kemp 25th Mar\1m Mdn Stks
             |\GB\Kemp 25th Mar\To Be Placed
      ...which kind of negates the point of using a treeview. Or I end up with every folder as a node of the same parent in the tree! E.g.:

      Code:
      |Horce Racing
             |GB
                  |Aintree Specials
                       |Top Jockey
                            |GB
                                 |Kemp 25th Mar
                                      |1m Mdn Stks
                                           |GB
                                                |Kemp 25th Mar
                                                     |To Be Placed

      Comment

      • elmariachi
        Junior Member
        • Feb 2009
        • 16

        #63
        First you need to retrieve the data. You should use GetEvents() for this starting with the root event (I'm guessing that you do this already).

        The process:
        Create a tree strcuture in your code (usually a node class that holds other nodes => tree).
        Get the root event and insert it as a root into your tree structure.
        Then get the first subelement (lets call it a) of the root event and insert it as a leave of the root into your structure. Then get the first sub element (lets call it aa) of 'a' and insert it as a a leave of 'a' into your structure.
        Do this with until you reach a subelement (aaaaa) that has no subelements. Then you move to the parent element (aaaa) of this subelement and go to the next subelement (aaaab) of 'aaaa'.
        When you follow this structure you will be able to populate a tree successfully.

        When reading from the tree you follow a similar pattern. Its called tree walk. The important thing is that you always use the same procedure. Just as an example: Instead of taking the first subelement you could also always take the last and go backwards. BUT: You always need to follow the same steps until you have reached the end of the tree.

        I can make a code example. Sice I personally don't populate the events I dont have some code already. It would probably be c# though.

        E

        Comment

        • Drifter
          Junior Member
          • Mar 2009
          • 30

          #64
          Has anybody done a straight port of the VBA code from this thread to C#. I know there is a C# sample posted, but purely as a learning exercise I am trying to port the VBA to C#, and my lack of knowledge is finding me out a bit on the 'unpack' modules. So, I'm interested in just a straight translation of the sample code.

          I am also curious why one would write the unpack module that way anyway: re-dimensioning the arrays then doing a string compare each step, instead of simply doing a split, finding the number of elements that gives, and creating the array from that value. That is what I do in my own app, and split off the header line for separate treatment. I think it is tidier, and though I haven't (read: can't yet!) profiled the 2 versions, I suspect it would be quicker too.

          some background: I have already written a functioning app to call the API in C# - crude, but working - however, coming from the 'proceduralist' world (rather more years ago than I'd like to 'fess up to) it is, in effect, one long function / method. I'd simply like to understand it better, improve my OO awareness, and C# coding ability.

          Thanks in advance
          Last edited by Drifter; 25-03-2009, 04:17 PM.

          Comment

          • Mumbles0
            Junior Member
            • Jan 2009
            • 240

            #65
            Reply to Dodgee (Re: TreeView)

            Great idea to use TreeView to show the markets!

            The standard way is to start with your eventTypeId and make successive calls to getEvents, adding the nodes of the TreeView as you go. But I think that you have been trying to build it by analysing the getAllMarkets response. Another great idea because it only requires one API call to get all the data of interest.

            I‘ve got some ideas on how to go about this. I will post a new Step soon.

            Comment

            • elmariachi
              Junior Member
              • Feb 2009
              • 16

              #66
              Originally posted by Mumbles0 View Post
              Great idea to use TreeView to show the markets!

              The standard way is to start with your eventTypeId and make successive calls to getEvents, adding the nodes of the TreeView as you go. But I think that you have been trying to build it by analysing the getAllMarkets response. Another great idea because it only requires one API call to get all the data of interest.

              I‘ve got some ideas on how to go about this. I will post a new Step soon.
              In fact to be able to use the getallmarkets would be fantastic. But the reason i didnt suggest it was that in the past I had the issue of path cutoffs.
              It would be fairly easy to traverse the path of a market into a tree. But it would need to be insured that if a path is cut off (which is not easy to detect) the get events method is used to retreieve the missing information.
              But it would of course be nice to be able to just make one call in order to populate the event tree.

              E
              Last edited by elmariachi; 26-03-2009, 09:29 AM.

              Comment

              • Mumbles0
                Junior Member
                • Jan 2009
                • 240

                #67
                Step 15. Using TreeView to show events and markets.

                The TreeView control provides an “explorer”-style user interface. Populating a TreeView with the hierarchy of events and markets provides convenient means to quickly get to a marketId of interest.

                The standard way is to start with your eventTypeId (returned by getActiveEventTypes) and make successive calls to getEvents, adding the nodes of the TreeView as you go. Each time you call getEvents you set its eventParentId parameter to an eventId returned from the previous call. When there are no more eventIds, you’ve reached the markets for this branch.

                An alternative approach (suggested by Dodgee) is to build the TreeView by analysing the getAllMarkets response. The big advantage here is that only one API call is required. Also, because you specify event types, countries, and timeframe when you call getAllMarkets, you only get the events and markets you are interested in.

                Make some space on the TestForm (there must be a bit left!) and drag on a TreeView control from the Toolbox. Size it to suit and change its name from TreeView1 to tvMarkets.

                Add this sub to, say, Module Unpack:

                Code:
                Friend Sub PopulateTreeView(ByVal AllMarkets As UnpackAllMarkets, ByVal TreeView As TreeView)
                  Dim Ids, Names As String(), Nodes As TreeNodeCollection
                
                  TreeView.Nodes.Clear()             'Start afresh
                  With AllMarkets
                    For i = 0 To .MarketData.Length - 1          'For each market
                      With .MarketData(i)
                        Ids = .EventHeirachy.Split("/")        'Array of Ids
                        Names = .MenuPath.Split("\")       'Array of names
                        Nodes = TreeView.Nodes          'Initial collection of child nodes
                
                        For j = 1 To UBound(Ids)               'For each event list item
                          If Not Nodes.ContainsKey(Ids(j)) Then
                            Dim Node As New TreeNode       'Add a new node if it doesn't exist
                            Node.Text = If(j <= UBound(Names), Names(j), .MarketName)
                            Node.Name = Ids(j)  'This is the key
                            Nodes.Add(Node)
                          End If
                          Nodes = Nodes(Ids(j)).Nodes     'Next level down
                        Next
                
                      End With
                    Next
                  End With
                End Sub
                This sub builds the TreeView structure based on the .eventHeirachy string. This is preferable to using .menuPath because duplicate names can occur. Note however, the node labels are derived from .menuPath.

                In Sub bMarkets_Click in the TestForm code locate the Dim AllMarkets.... line and insert the call to our new PopulateTreeView sub:

                Code:
                   
                 Dim AllMarkets As New UnpackAllMarkets(.marketData)
                 PopulateTreeView(AllMarkets, tvMarkets)       '<<< Add this
                 With AllMarkets
                 .....
                Test by clicking the “Markets” button. The TreeView should now display the “tree” for the markets returned by getAllMarkets.

                Now add an event handler to fire when we click on a node. In the Class Name textbox select “tvMarkets”. In the Method Name textbox select “AfterSelect” to add the event handler Sub tvMarkets_AfterSelect. Add this code:

                Code:
                Private Sub tvMarkets_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles tvMarkets.AfterSelect
                  If e.Node.Nodes.Count = 0 Then
                    Beep()
                    Dim marketId As Integer = Val(e.Node.Name)    'This is the selected marketId
                  End If
                End Sub
                Parameter e contains a reference to the selected node. If this node is a market, its marketId is now available. Quite likely you will make a getMarket call here.
                Last edited by Mumbles0; 26-03-2009, 07:25 PM.

                Comment

                • Mumbles0
                  Junior Member
                  • Jan 2009
                  • 240

                  #68
                  Reply to Drifter...

                  Thanks for the post.

                  Firstly, the code in this thread is VB2008, not VBA. While the two languages are related, they are not the same. VB2008 is Microsoft’s current incarnation of VB.NET.

                  Although I’m not a C# expert, I’m sure it would be quite easy to translate the code in this thread into C#. (I don’t think you have to do much more than reverse the wording of the declarations, replace the End Ifs with curly things, and throw in a few semi-colons; )

                  Note that the title of this thread is “Using VB2008 to access the Betfair API...” It is a “hands-on” tutorial which, as you might expect, focuses on VB2008. To avoid confusing some readers, I think C# sample code best belongs on another thread.

                  It’s good to see someone closely analysing the code. Please note that I have included these unpacking classes primarily to demonstrate working code that is not too complex for the benefit the tutorial. The examples are not intended to form a library of high-performance classes and I have never believed there is no room for improvement. Why do it this way? If you set 10 people the same programming task you would probably get 10 different ways of doing it.

                  Your suggestion to unpack using the String.Split method is good. What I plan to do now is rewrite one of the classes this way and compare it to the existing one. Because most of the detail is involved in converting the individual items, I am expecting the amount of code to remain about the same. Perhaps the resulting class will run faster. The current one tends to struggle when unpacking very large strings.

                  Like yourself, my background is with procedural languages. The transition to OO has been very gradual. Indeed it takes time to get one’s mind around the objects. This may refect in my coding which I’m sure contains elements of both approaches. My aim is to produce practical, efficient code that works, rather than to become too preoccupied with abstract notions.

                  Regards, M0

                  Comment

                  • elmariachi
                    Junior Member
                    • Feb 2009
                    • 16

                    #69
                    .. understood

                    Im not gonna post any c# code directly into the vb threads anymore. I think your correct when you say that this might confuse people.

                    When it comes to revising the unpacking methods especially regarding using the split I have alredy posted some code that would enable you to do this (GetMarketPricesCompressed).
                    I considered using the String.Split() method but it does not provide the possibility of excluding escaped characters. So I created the appropriate regular expressions to make this possible. Luckily the .NET Regex engine has a functionality very simitlar to the String.Split() called Regex.Split() which enables you to provide a regular expression that is used for splitting the provided string.
                    This works very well even when decompression 20 responses per second.

                    Since its in c# I will just link to it (I hope thats better)
                    http://forum.bdp.betfair.com/showthread.php?t=173

                    E

                    Comment

                    • Drifter
                      Junior Member
                      • Mar 2009
                      • 30

                      #70
                      OK. Sorry about the ref to VBA - simply not being aware that the Basic language in VS2008 was not called VBA. Noob.

                      I put my comment here originally, simply because I thought it was more relevant to the tutorial, than to the finished app sticky upstairs. Apologies if that was the wrong approach. I feel that the comments about the strategy used in the Unpack class are, in any case, language independent. The comment about C# porting was really to only find out if others were also trying it, simply because (although, as you say, it isn't unduly hard), I do have one issue, and that is how to handle the call to, and definition of, the 'New' method in Unpack. It seems to me that I may have to use a delegate to make the function call here, but I'm not sure, and help would be appreciated in understanding how this call would be made in that language.

                      Elmariachi: I used a String.Replace to get around the escape characters, just replacing them with something very un-obvious (a string of '@' characters), rather like one would do with a regex. I'm sure the regular expression will be quicker (maybe tidier too), though for the number of calls it might not make so much difference. End of C#...

                      Thanks very much for the efforts you are both making with the tutorial in any case, it is extremely useful to me. Is there a case though, based on your reply, for separating out the tutorial completely (and effectively making it read-only by locking it), and running a separate thread for comments, questions and so on?
                      Last edited by Drifter; 28-03-2009, 08:45 AM.

                      Comment

                      • Dodgee
                        Junior Member
                        • Jan 2009
                        • 17

                        #71
                        Treeview code

                        That code works a treat!

                        Thanks Mumbles and elmariachi for your input; I figured using getAllMarkets might be the most efficient way of doing things but struggled with the logic of populating the treeview.

                        Mumbles' code does the job in a far more concise way than mine was shaping up to be!

                        Comment

                        • Mumbles0
                          Junior Member
                          • Jan 2009
                          • 240

                          #72
                          Revision to Step 6. (Unpacking Response Strings)

                          The unpacking class UnpackAllMarkets in step 6 has now been revised. it now uses the String.Split method to separate the substrings. (The original code used a successive substring retrieval method.)

                          This change has been done after considering the comments of Drifter (and others).

                          The revised code runs very much faster and better handles the escape sequence ("\:"). The speed improvement is particularly noticeable when processing a large number of markets (2500 markets ran 1000 times faster!).

                          Soon I intend to revise Step 10 (getCompleteMarketPricesCompressed) and Step 14 (getMarketPricesCompressed) along the same lines.
                          Last edited by Mumbles0; 05-04-2009, 10:10 AM.

                          Comment

                          • Drifter
                            Junior Member
                            • Mar 2009
                            • 30

                            #73
                            1000 times! Now that is what I call a performance gain!

                            code looks somewhat similar - no surprise - though if you want to know what the 1970 base date is for, it is the date that the UNIX world considers to be the start of the universe, and is why there will be another awkward Y2K style date problem in 2038 when 32 bit maxdate occurs! Of course, nobody will be using 32 bit by then - just like nobody was using 2 digit dates in 1999...

                            It may be that this standard creeps into the PC world, from the US Department of Defense requirement that all HW/SW vendors demonstrate POSIX compliance (this includes Windows, Apple, VMS and the rest) in order to be allowed to tender for DODS contracts. And yes, they really do spell it 'Defense'. (Off topic again. I know...)
                            Last edited by Drifter; 10-04-2009, 07:57 AM.

                            Comment

                            • willyray1
                              Junior Member
                              • Apr 2009
                              • 9

                              #74
                              Originally posted by Mumbles0 View Post
                              The TreeView control provides an “explorer”-style user interface. Populating a TreeView with the hierarchy of events and markets provides convenient means to quickly get to a marketId of interest.
                              Mumbles0 - firstly many thanks for posting this great tutorial, I've quickly got up to speed on all things API, although still a very long way to go!!

                              With Step 15 we are only able to populate a single market at a time. Ideally it would be easier if we first load the treeview with all the events, then when we click the event, the markets are then displayed. e.g.

                              First load:
                              Rugby Union
                              Snooker
                              Soccer
                              Soccer - Fixtures... etc

                              Click Soccer:
                              Rugby Union
                              Snooker
                              Soccer
                              English Soccer
                              Barclays Prem...
                              Championship... etc
                              N Irish Soccer
                              Scottish Soccer
                              Serbian Soccer
                              Welsh Soccer
                              Soccer - Fixtures

                              This **should be ** straight forward as we have all the event id's and all the market id's relating to the event. Is there an easy way of tweaking the code to achieve this? I can load all the events easy enough and load single markets.

                              Comment

                              • willyray1
                                Junior Member
                                • Apr 2009
                                • 9

                                #75
                                Well it took a while, but I sussed it!!

                                Added this to the bEvents_Click

                                Code:
                                With .eventTypeItems(i)
                                    'Dim AllEvents As New UnpackAllMarkets(.marketData)
                                    'PopulateTreeView(AllMarkets, tvMarkets)
                                    [B]tvMarkets.Nodes.Add(.id, .name())[/B]
                                    Print(.name & " (" & .id & ")")
                                End With
                                This loads all the events to the treeview with the id being the key. When you click the Markets button, it adds the children to the parent node - hey presto!! Just needs a bit of tidying up and its on to the main programming!

                                Comment

                                Working...
                                X