A whitepaper Jon Box and I wrote for MSDN on testing for the presence of a network connection in the .NET Compact Framework was just published here. Enjoy.
Wednesday, July 28, 2004
Testing for the Network
Posted by Dan Agonistes at 9:56 PM 1 comments
Friday, July 23, 2004
Triumph and Tragedy in Mudville
This is a collection of 30 plus essays on baseball written by the late Harvard paleontologist Stephen Jay Gould over the last 20 to 30 years. Among them are two original pieces on forms of streetball in New York City when Gould was growing up and a piece discussing the lure of baseball for intellectuals like himself (which he views as purely contingent on time and place).
There is also a long tribute to Gould (he died in May of 2002) in the forward written by David Halberstam (author of Summer of '49). Many of the remaining essays appeared in various places such as the New York Times Review of Books, some of which I've read before but many of which I hadn't seen. They range from book reviews to short eulogies (of Mickey Mantle for example) to essays. One of his most famous is his essay on the disappearance of the .400 hitter originally written in 1986 for Discover magazine. He, like George Will in perhaps my favorite baseball book Men at Work, views it simply as the natural consequence of of an increasing level of play that comes closer to the "right-wall" of human ability coupled with the increasing maturity of the game. This increasing level of play tends to decrease the differences between average and stellar performers. As a result, since the mean batting average has remained roughly .260 since the 1940s, there are fewer players at both the left and right ends of the spectrum. This also tracks very well with a book that came out a couple years ago that rated the greatest hitters (for batting average) of all time through a series of statistics and determined that Tony Gwynn was the greatest.
Gould's writing is always interesting and even though he was a life long Yankees fan, he rightly despised the DH and aluminum bats. Baseball fans will find plenty to like here.
Posted by Dan Agonistes at 9:01 PM 0 comments
Tuesday, July 20, 2004
Baseball Encyclopedia Errata
Just found out that errors and omissions from the Baseball Encyclopedia that I bought a few months back can be found here. Some fairly significant things like the omission of serveral player records.
Posted by Dan Agonistes at 8:21 AM 0 comments
Sunday, July 18, 2004
Relativity and OPS
My contention in a previous post was that OPS (on base + slug) is a useful measure of offensive production because of its simplicity, comparative ability, and correlative value. However, when ranking the greatest single seasons in OPS only three players, Barry Bonds, Babe Ruth, and Ted Williams, made the top 10 seasons. Could this be the result of some bias in favor of these particular players? For example, one obvious thought that comes to mind is that since homeruns have been flying out of the park at an increased rate since 1993 (“chicks dig the long ball”) it is easier for a player like Barry Bonds playing in the context of an expanded run environment to amass large OPS numbers by increasing their slugging percentages (the average number of plate appearances per homerun in the period 1960-1992 was about 47, from 1993-2003 it was 35, in other words a player with 600 plate appearances would hit about 12 and half homeruns in the 1960-1992 period and almost 17 in the 1993-2003 period). Another thought is that perhaps Ted Williams was inordinately helped by Fenway Park with its Green Monster and short right field line and Babe Ruth by playing in a park that was after all, the house that he built.
Correcting for League and Year
To see if there is some hidden bias here we can first correct for the context by calculating the league average OPS for the 10 seasons in question and then normalizing the individual’s OPS against the league average, a concept first introduced in The Hidden Game of Baseball. For example, in 2001 the National League OPS was 756, a very high number historically. By taking Barry Bonds’ OPS of 1379 and dividing it by the league average (1379/756) we can calculate a Normalized OPS (NOPS) of 1.82, or simply 182 for short. By performing the same calculation with Babe Ruth’s 1920 season (the same raw OPS of 1379 in a league where the average was 730) his NOPS comes out to 189, a little ahead of Bonds. Here are the before and after rankings.
Raw OPS
2002 NL Barry Bonds SFN 1381
2001 NL Barry Bonds SFN 1379
1920 AL Babe Ruth NYA 1379
1921 AL Babe Ruth NYA 1359
1923 AL Babe Ruth NYA 1309
1941 AL Ted Williams BOS 1287
2003 NL Barry Bonds SFN 1278
1927 AL Babe Ruth NYA 1258
1957 AL Ted Williams BOS 1257
1926 AL Babe Ruth NYA 1253
Normalized OPS Raw LgOPS NOPS
1920 AL Babe Ruth NYA 1379 730 189
2002 NL Barry Bonds SFN 1381 741 186
2001 NL Barry Bonds SFN 1379 756 182
1921 AL Babe Ruth NYA 1359 761 179
1957 AL Ted Williams BOS 1257 707 178
1923 AL Babe Ruth NYA 1309 734 178
1941 AL Ted Williams BOS 1287 728 177
2003 NL Barry Bonds SFN 1278 749 171
1926 AL Babe Ruth NYA 1253 739 170
1927 AL Babe Ruth NYA 1258 747 168
Since these ten seasons were first picked because of their raw OPS numbers it’s now appropriate to open up the field and recalculate the single season leaders taking into account their normalized OPS.
Normalized OPS Leaders Raw LgOPS NOPS
1920 AL Babe Ruth NYA 1379 730 189
2002 NL Barry Bonds SFN 1381 741 186
2001 NL Barry Bonds SFN 1379 756 182
1921 AL Babe Ruth NYA 1359 761 179
1923 AL Babe Ruth NYA 1309 734 178
1957 AL Ted Williams BOS 1257 707 178
1941 AL Ted Williams BOS 1287 728 177
2003 NL Barry Bonds SFN 1278 749 171
1926 AL Babe Ruth NYA 1253 739 170
1946 AL Ted Williams BOS 1164 690 169
As you can see the same three hitters still dominate the list, however, the distribution has changed somewhat with Ted Williams garnering another spot for his 1946 season in a league with a low OPS of 690 and Babe Ruth losing his 1927 season when the league put up a fairly high OPS of 747. Williams’ 1957 season now also looks better in this light moving from 9th to 5th place. And most obviously Babe Ruth’s 1920 season now tops the list with an NOPS of 189. So in answer to part of our question we can fairly confidently say that these three hitter’s accomplishments were not inordinately helped by playing in leagues that were hitter’s paradises. In fact, the first player not of this ruling triumvirate to make the list is Mickey Mantle with his 1957 season (NOPS of 167). The only other contemporary player to make the top 20 is Mark McGwire with his famous 1998 season and an NOPS of 166 tied for 15th.
However, hitters that played in extremely low scoring run environments should be greatly helped by normalizing OPS. For example, consider Willie McCovey’s 1969 season and Carl Yastrzemski’s 1967 seasons.
Raw OPS LgOPS NOPS
1969 NL Willie McCovey SFN 1108 686 162
1967 AL Carl Yastrzemski BOS 1040 651 160
Before normalization McCovey in 1969 ranked as tied for 70th all-time with a raw OPS of 1108. After correcting for a league in which pitchers dominated with an OPS of 686 he jumps to tied for 23rd with an NOPS of 162. Even more dramatically Yaz in 1967 moves from tied for 166th to tied for 27th place.
Correcting for Ballpark
But adjusting for the run environment of the league in which a player plays is only part of the context. The park in which the player plays his home games is another significant aspect. Intuitively this makes sense. It seems obvious that Larry Walker gets a boost from playing in Coors Field while Willie McCovey was hurt by playing in Candlestick Park. To take this into account sabermetricians have devoted themselves to calculating “park factors” or “park effects” for each of the major league parks. Historically this has been done by calculating a Batter Park Effect or BPF and a Pitcher Park Effect or PPF for each team. The calculation of these effects as documented The Hidden Game of Baseball involves not only comparing the scoring in each park with the scoring at other parks but also taking into account that there is a "home cooking" bias where batters naturally hit and pitch better at home (a fact well documented in Curve Ball). In addition, the calculation allows for the fact that a team's hitters do not have to face its pitchers and vice versa. The BPF and PPF are expressed as a percentage of the league average, in other words a BPF of 1.06 would mean that the batter's home park gives him a 6% advantage over the league and a PPF of .95 means that the park helps pitchers to the tune of 5%. Although factors can and are calculated for different offensive events, homeruns, doubles, triples, etc. the overall BPF is calculated based on runs scored. Here are the BPF and PPF as calculated for 2003 sorted by BPF.
Team BPF PPF
MON NL 118 116
KCA AL 113 112
COL NL 112 111
ARI NL 111 109
TEX AL 110 109
TOR AL 105 104
BOS AL 105 104
HOU NL 104 103
MIL NL 102 102
MIN AL 102 102
TBA AL 100 100
CIN NL 100 100
NYN NL 99 99
PIT NL 99 99
SFN NL 99 100
CHN NL 99 99
CHA AL 99 99
ATL NL 97 97
SEA AL 97 98
NYA AL 96 97
SLN NL 96 97
PHI NL 95 96
BAL AL 95 96
DET AL 95 95
FLO NL 94 94
LAN NL 93 94
ANA AL 93 94
CLE AL 93 94
OAK AL 93 94
SDN NL 91 92
Fortunately, the BPF and PPF have been calculated and are present in the Lahman database and so in order take into account the home park we simply need to multiply the NOPS by the BPF divided by 1,000. Here are the single season NOPS leaders shown previously re-sorted with a new column for normalized for park effects.
Raw OPS NOPS NOPS/PF
2002 NL Barry Bonds SFN 1381 186 204
2001 NL Barry Bonds SFN 1379 182 200
1920 AL Babe Ruth NYA 1379 189 182
1921 AL Babe Ruth NYA 1359 179 175
1923 AL Babe Ruth NYA 1309 178 175
1941 AL Ted Williams BOS 1287 177 174
2003 NL Barry Bonds SFN 1278 171 173
1926 AL Babe Ruth NYA 1253 170 173
1957 AL Ted Williams BOS 1257 178 168
1946 AL Ted Williams BOS 1164 169 159
So given that Bonds has played in a relatively poor park for hitters (BPFs of 91 in 2001 and 2002) gets helped while Williams is hurt by the high BPFs of Fenway Park that are consistently over 100. And so it is once again appropriate to recreate the top 10 list with park effects.
Raw OPS NOPS NOPS/PF
2002 NL Barry Bonds SFN 1381 186 204
2001 NL Barry Bonds SFN 1379 182 200
1920 AL Babe Ruth NYA 1379 189 182
1923 AL Babe Ruth NYA 1309 178 175
1921 AL Babe Ruth NYA 1359 179 175
1941 AL Ted Williams BOS 1287 177 174
2003 NL Barry Bonds SFN 1278 171 173
1927 AL Babe Ruth NYA 1258 168 173
1926 AL Babe Ruth NYA 1253 170 173
1931 AL Babe Ruth NYA 1195 162 172
Since Williams is hurt so much by Fenway Park he almost slips off the list entirely with only his 1941 season remaining. Ruth, however, now adds his 1927 and 1931 seasons when Yankee Stadium held a slight advantage for the pitcher.
Incidentally, Willie McCovey in 1969 moves up to tied for 11th with 165 when considering the tough hitting environment of Candlestick Park while Yaz in 1967 moves down to tied for 102nd at 148. So who is hurt most by taking into account park effects? As you might have guessed it is those who have played for the Colorado Rockies. In fact, Rockies take the top 35 spots when calculating the difference between NOPS and NOPS/PF with Todd Helton’s 2000 season taking top honors when his NOPS was 150 and NOPS/PF was 115. Conversely, Barry Bonds 2001 and 2002 seasons are most helped when park is taken into account raising his score by 18. For Cubs fans like me it’s interesting to note that Sammy Sosa’s 2000 season was tied for 2nd with a 15 point bump up to 149 once park effects were taken into account. Those who follow the Cubs know that weather patterns are the largest variable in whether or not Wrigley Field is a hitter’s delight or a pitcher’s best friend. Those who aren’t Bonds fans might take issue with assuming that the Giants home park hurts Bonds since it was built with a short right field porch with Bonds specifically in mind. Certainly Bonds, being a left-handed hitter, is hurt less by the park than are right handers and so I have a degree of sympathy for that argument. However, I don’t have any data that supports or contradicts the argument at this point. A similar argument could made against Ruth.
So does any of this change our perceptions of who had the greatest single seasons in history? Not really. Bonds, Ruth, and Williams still dominate the top spots and by virtue of Ruth taking 6 of the 10 a strong argument can be made that he was indeed the greatest hitter of them all.
On the other end of the spectrum Niefi Perez has somehow managed to grab two of the worst nine seasons in history with NOPS/PFs of 64 in 2002 and 71 in 1999.
Final Thoughts
Three additional thoughts might come to your mind when considering whether these were the greatest seasons in baseball history.
* Where's the defense? This ranking does not include defense and so can only be used as a ranking of the greatest offensive seasons in history. Although sabermetricians have tried for many years to develop defensive measures that quantify how many runs an individual saves for his team, in the end most of these schemes have difficulty. This is primarily because defense is a much more complex concept in baseball (more akin to defensive backs in football) than offense and doesn’t lead itself to quantification very easily. As Branch Rickey once famously said “There is nothing on earth anybody can do with fielding.” That said there are sabermetric measures such as Defensive Efficiency Rating (DER) and Zone Rating (ZR) that attempt to measure defense more accurately than the traditional counting stats that include put outs, assists, and errors. Bill James, in his book Win Shares, also tries to assign value to defense through a more holistic approach that takes into consideration run prevention at the team level.
* What about opportunities? As mentioned in the previous post one of the strengths of OPS is its simplicity. One of the costs of that simplicity is that OPS has nothing to say about the opportunity a player had to garner his OPS. In other words, which player is more valuable, one with an OPS of 850 who had 600 plate appearances or one with the same OPS who had 200 plate appearances? Obviously, the former since an 850 OPS is pretty good and so finding four players with an 850 OPS over 200 at bats will likely be difficult. In the rankings presented in this post this problem is largely ignored by selecting only those players with 502 or more plate appearances in a season, in other words by only selecting those players who played every day. To address this problem Runs Created per Game (RC/G) takes into account opportunities by considering how many outs a player has consumed – the most valuable resource a team has – while amassing their offensive numbers.
* What about Ty Cobb? Many readers will have noted that Ty Cobb is conspicuously absent from this list and that Cobb is often talked about in the same context with Ruth and Williams. In fact, Cobb first appears on the list tied for 33rd at 160 for his 1917 season right behind Sosa’s 161 in 2001. There are two reasons why this is the case. First, some of Cobb’s perceived value was his foot speed and base stealing ability, neither of which are particularly visible in OPS. Second, OPS is largely a measure of extra-base hitting and Cobb only hit as many as 12 homeruns twice. In his 1917 season, however, he hit 44 doubles, 24 triples, and 6 homeruns. The fact that OPS is correlated so strongly with run scoring indicates that players like Cobb who focused on hitting for average at the expense of power (assuming they could do either of course) did and continue to do a disservice to their teams by forsaking power. In short, if the often told story is true of Cobb hitting three homeruns in a game only to prove to writers that power hitting was not that difficult, then Cobb was mistaken in going back to his former style.
Finally, let's recalculate the 2003 leaders by applying both the correction for league and for park.
Raw OPS LgOPS NOPS/PF
Barry Bonds SFN 1278 749 173
Albert Pujols SLN 1106 749 154
Gary Sheffield ATL 1023 749 141
Jim Edmonds SLN 1002 749 140
Jim Thome PHI 958 749 135
Todd Helton COL 1088 749 129
Jason Giambi NYA 939 761 128
Carlos Delgado TOR 1019 761 128
Chipper Jones ATL 920 749 127
Manny Ramirez BOS 1014 761 127
It should be noted that the historical rankings take into consideration seasons since 1900 for players with 502 or more plate appearances and that for seasons with HBP and SF recorded they were taken into account. In addition, others have calculated similar adjusted values, some much more complicated, including the Adjusted OPS or OPS+ on baseball-reference.com and PRO+ in Total Baseball.
Posted by Dan Agonistes at 11:08 PM 2 comments
Saturday, July 17, 2004
What the heck is OPS?
Baseball Tonight's Harold Reynolds has been known to ask this question in a derisive tone complete with hand waving when discussing statistics. You may have noticed that I've periodically used OPS when discussing the relative merits of players or for comparison. For the sabermetrically challenged OPS is defined as:
OPS = On Base Average + Slugging Percentage
It couldn't be simpler. Since OPS is simply the addition of these two the long formula would be:
OPS = ((H+BB+HBP)/(AB+BB+HBP+SF))+(TB/AB)
Of course, since the denominators of the two values being added are not the same it's not really mathematically correct to show OPS as .892 and so in many places you'll see it simply listed as 892.
So why use OPS when slugging percentage and on base percentage are so readily available? I'll give three reasons:
Bonds SFN 1278
Pujols SLN 1106
Helton COL 1088
Sheffield ATL 1023
Delgado TOR 1019
Ramirez BOS 1014
Edmonds SLN 1002
Rodriguez TEX 995
Nixon BOS 975
Ortiz BOS 961
And the single season all-time leaders since 1900:
2002 NL Barry Bonds SFN 1381
2001 NL Barry Bonds SFN 1379
1920 AL Babe Ruth NYA 1379
1921 AL Babe Ruth NYA 1359
1923 AL Babe Ruth NYA 1309
1941 AL Ted WilliamsBOS 1287
2003 NL Barry Bonds SFN 1278
1927 AL Babe Ruth NYA 1258
1957 AL Ted WilliamsBOS 1257
1926 AL Babe Ruth NYA 1253
The list is dominated by just three players. But could it be that the conditions under which these three played helped them dominate? To discover if this is the case in a future post I'll talk about how we can "relativise" OPS to take into account the context in which these hitters performed.
For these reasons you'll see me continue to use OPS. However, in order to get a baseline here are the average OPS numbers for 2003 (for non-pitchers):
AL 762As a result, an OPS below 700 is bad, above 775 is pretty good, and above 875 is very good. These numbers have been pretty consistent since 1993.
NL 771
Posted by Dan Agonistes at 9:43 PM 0 comments
Addendum to Batting Order
A week or so ago I blogged about batting order and quoted The Hidden Game of Baseball as poo-pooing the idea that monkeying around with the batting order actually produced more runs. One thought that occurred to me after posting was that Palmer and Thorn had used the average statistics at each position in the majors from 1969-1971 along with simulation in order to come to their conclusions. In fact, here are the averages for the nine positions they used in their simulation:
AVG SLUG OBP
1 .270 .374 .337
2 .267 .373 .333
3 .287 .476 .373
4 .280 .470 .363
5 .268 .430 .344
6 .256 .395 .331
7 .250 .359 .318
8 .235 .313 .302
Of course, my comments were directed towards Dusty Baker's lineup selection, which today looked as follows.
AVG SLUG OBP
Walker .282 .492 .365
Ordonez .164 .262 .190
Sosa .273 .559 .362
Alou .273 .510 .327
Patterson .276 .448 .329
Lee .302 .518 .371
Macias .289 .405 .304
Bako .192 .247 .280
Maddux .143 .143 .167
What should be immediately obvious and what I hadn't thought of when I wrote my first post is that the variability in an individual team's lineup is almost always going to be greater than that in the league as a whole. And so in the case of the Cubs, batting their worst hitter (Ordonez) second and their best on base percentage hitter (Lee) 7th regularly has a greater impact than a simulation using the average at those positions would show. How big the difference is could be determined with another simulation but I'd be suprised if wasn't on the order of a couple of wins (around 20 runs).
Posted by Dan Agonistes at 6:32 PM 0 comments
Friday, July 16, 2004
The Four Man Rotation
Here's an interesting article published on Baseball Prospectus by Rany Jazayerli. The article basically explains how BP calculates Pitcher Abuse Points (PAP), something the Cubs and Dusty Baker might keep in mind given the high pitch counts Mark Prior (113.3 pitches per start, tops in the NL in 2003 and now perhaps headed to the DL for the second time with elbow trouble), Carlos Zambrano (106.4 pitches per start in 2003), and Kerry Wood (110.7 pitches per start in 2003) regularly incur.
More interesting though are the recommendations that come from their analysis of PAP. Basically, they advocate going back to the historical four-man rotation but monitoring pitch counts more carefully and then using the starters in relief on their regular throwing days. In all this would give starters more innings pitched (280-290) while not adversely affecting their arms and since your starters are generally your best pitchers, would lead to more victories.
I've seen this theory proved out anecdotally in baseball simulation games which my brother enjoys. He regularly uses elements of this approach and still wins with average teams. However, in the real world I don't hold out much hope that any team will actually try it in the near future. Baseball is by its nature a conservative institution.
For another view on the conservative nature of baseball check out Alan Schwarz's excerpt of his new book The Numbers Game, which I'm going to run out and pick up very soon. Here he recounts how the new sabermetric knowledge first widely published in the 1964 book Percentage Baseball was shunned by almost everyone in the industry and of course is still largely ignored by those in the inner-circle.
Posted by Dan Agonistes at 3:15 PM 0 comments
Wednesday, July 14, 2004
Midterm Report
So during the All-Star game respite I thought I'd give an assessment of both the Royals and Cubs.
Royals (31-54 15.5 games out in the central)
After starting 4-2 its all been down hill... The poor performances of Anderson and May in the starting rotation and the lackluster hitting by everyone except Ken Harvey and Carlos Beltran quickly sunk any hope the Royals had to contend in a weak AL Central. The only bright spot has been rookie Zack Grienke who will start the 2nd half tomorrow night against the Twins has a 3.86 ERA (56 IP, 49 H, 12 BB) in 9 starts. Lack of run support has led to his 1-6 record. His only weakness thus far has been a tendency to give up the long ball (9 so far). Once it was clear the Royals had no hope they unloaded Curtis Leskanic, Jason Grimsley, and Carlos Beltran. I would look for Joe Randa and Matt Stairs to be next and perhaps Scott Sullivan.
Injuries have also played a big part in the disaster - 10 players are currently on the disabled list including Juan Gonzales, Benito Santiago (60 day DL), Jeremy Affeldt, Aaron Guiel, and Joe Randa - all players the Royals had hoped would contribute. This isn't to mention the pitchers Kyle Snyder, Kevin Appier, Miguel Asencio, Mike MacDougal, and Runelvys Hernandez, all of whom it was thought would contribute this year. In fact, other than Sweeney, Berroa, and Harvey, none of the projected starters will likely contribute much more this season. It doesn't make sense to play Gonzales or Santiago anymore this season either even though Santiago has another year on his contract. Hopefully he'll retire after the season.
Things to look forward to in the second half are seeing if David DeJesus can take over the centerfield job, seeing if newly acquired John Buck can actually hit at the major league level (he's looked overmatched thus far), and hoping that the Royals can finally make an assessment as to whether Dee Brown will actually have a major league career. They're also going to give former prospect Ruben Mateo some extended time to see what he can do although when Aaron Guiel comes back soon they'll have to split time amongst the four. On the pitching side Mike Wood (also obtained in the Beltra deal) so far doesn't look too promising and everyone else other than Grienke and Affeldt are just spare parts.
As I've said before I think the Royals front office did a fine job last winter. What's gone wrong (with the exception of trying to make Affeldt a starter) has largely been out of their control. Recently David Glass said that he expected the payroll to remain in the $50M range. And so with Beltran's salary freed up as well as that of Gonzales, Stairs, Randa, Grimsely, and Leskanic, the Royals should have some money to work with to try and sign a young pitcher perhaps or a corner outfielder.
Cubs (47-40, 7 games out in the NL Central, 1 game out in the Wild Card)
The story of the first half for the Cubs has been injures and unexpected contributions. In terms of injuries Mark Prior, Kerry Wood, Mark Grudzielanek, Mark Remlinger, Sammy Sosa, Alex Gonzales, and Joe Borowski have all been or are still on the disabled list. Aramis Ramirez is also now injured although not on the DL. Where this has hurt the Cubs the most is at shortstop where they've been forced to play Rey Ordonez and Ramon Martinez. Rumors are flying that the Cubs are working a deal for Nomar Garciapara, which would certainly help the struggling offense.
However, they've gotten great contributions from Todd Hollandsworth, Tom Goodwin, Jose Macias, Glendon Rusch (4-1 4.06) and particularly Todd Walker (.863 OPS) off the bench. Walker's contribution was so vital that I question putting Grudzielanek back in the lineup. At least they should be platooned with Walker taking most of the at bats and perhaps playing third when Ramirez sits. Other starters including Moises Alou (.839 OPS) and Ramirez (.924 OPS) particularly have picked up the slack as well. Derrek Lee (.891 OPS) and Corey Patterson (.772 OPS), after slow starts are now hitting as well.
Overall the outlook for the second half is all good. With the big 5 in the rotation the Cubs should be able to look forward to not having to score that many runs thankfully and still be competitive night in and night out. I don't hold out great hopes for winning the NL Central although Cardinals pitchers Suppan and Carpenter are vulnerable for let downs. A key for the Cubs in the 2nd half is being able to beat the Brewers and based on the 3 game sweep they endured last week it might be an uphill battle. With their right-handed dominated lineup they're are vulnerable to hard throwing right-handers like Ben Sheets. The Cubs start the second half in Chicago tomorrow night with Prior against Doug Davis. Can't wait.
Posted by Dan Agonistes at 8:47 PM 0 comments
Wild Pitch
I've added a new baseball blog to my list of links on the right. Wild Pitch is written by fellow SABR member Ray Flowers who, in addition to his blog, writes primarily for Drafthelp.com and athomeplate.com. He has a nice piece on Carlos Beltran and park effects here as well.
Posted by Dan Agonistes at 7:58 AM 0 comments
Sunday, July 11, 2004
Fully Trusted Code in .NET
A great article by Keith Brown. Some pretty major items here relating to fully-trusted code that were enlightening. Beware.
Posted by Dan Agonistes at 10:21 PM 0 comments
Benjamin Franklin: An American Life
Eripuit coelo fulmen sceptrumque tyrannis - French statesman Turgot
This famous epigram translated "he snatched lightning from the sky and the scepter from tyrants" neatly summarizes the two sides of Franklin (1706-1790) that predominate in this recent biography of Franklin by Walter Isaacson. I had wanted to read this book when it first came out largely because of the relatively negative view of Franklin I had gotten from reading David McCullough's John Adams.
Although not as well written as the McCullough book Isaacson does a good job of covering the bases detailing Franklin's life in a strictly chronological portrait beginning with his family's background (and the interesting derivation of the Franklin name) in England before his father immigrated to America in 1683. He then traces Franklin from his earliest apprenticeship at his brother's print shop at the age of 10 to his decisive move at 17 from Boston to Philadelphia and his somewhat obsessive drive to make something of himself through industriousness. From there his life as an entrepreneur and "leather-apron" (a middle class merchant) in the printing industry takes Franklin to London and back as he grows in both wealth and influence through the publication of his yearly Poor Richard's Almanak starting in 1733 and his often satirical essays and letters. Isaacson details many of the pithy sayings Franklin became famous for and notes how many of them (more than 90% in Franklin's own estimation) were ancient sayings that Franklin was able to recast in his homespun manner. During this time Isaacson recounts how Franklin tried to bring organization to all his activities and how he acted out his personal theology that "serving your fellow man is the best service to God" in organizing public services projects that started with his own philosophical and business club called the "Junto" which later spread to starting a fire brigade, paving and lighting streets, creating a lending library, starting a hospital, and the University of Pennsylvania.
Franklin retired at the age of 42 to pursue his intellectual and scientific pursuits (he never had a formal education being denied attendance at Harvard by his frugal father) and there is a great chapter on his experiments with electricity and lightning, musical instruments, stoves, and other inventions. Of course Franklin's greatest fame came from his theories on electricity which resulted in his proposal for the invention of the lightning rod in 1750. One of the interesting aspects of the story well recounted in the book is that Franklin's proposal was translated into French after being published in England and was verified on May 10, 1752 a month before Franklin's own famous verification using a kite and key. Isaacson also does a good job explaining the significance of an invention that we all take for granted that saved large amounts of property and lives and even had theological implications. Although Franklin's scientific endeavors had theoretical impact, Isaacson stresses that Franklin was not a theorist and was best at discovering practical uses for his discoveries.
From Franklin's interest in public service projects (and his own self-interest in the circulation of his newspaper and almanacs) he became involved in the Pennsylvania Assembly and postal service and eventually became postmaster (a job that would expose him, more than any of the founding fathers, to the expanse of the colonies and give him a perspective on their unification). From here his political career was launched and he was first elected to the assembly in 1751. While in the assembly his natural distaste for authority led him into conflicts with the proprietors of Pennsylvania, the Penn family, over taxes and defense from Indians. This led eventually to his being appointed by the assembly as their spokesperson in London where he traveled in 1757. From that point on Franklin would only return to America twice, once in 1763-1764 and again at the crucial juncture 1775-1776, living in London and then in Paris until finally returning home for good in 1785. His dealings in London included his work for Pennsylvania and later Georgia with the court and parliament and his role in repealing the Stamp Act before his final humiliation before parliament in 1774. His role at the Continental Congress in 1776 is well told as well as his interaction with Jefferson and Adams in drafting The Declaration. His return to Paris in 1776 as one of the agents of the new Continental Congress was filled with intrigue and dissension with his fellow American commissioners as he was tasked with extracting money from the French court and eventually in 1783 helping broker the peace between Britain and the new republic. After returning home to great fanfare he played the wise sage and helped create the compromises necessary in forming the Constitution during the convention of 1787. Through it all, Isaacson portrays Franklin as a pragmatist who stood on a few solid principles but who was willing to negotiate.
A few of the other interesting tidbits in the book were:
I'd certainly recommend this book to anyone who wants to get a mental portrait of Franklin and although certainly positive in its overall take, it appears a fair portrayal. It has a good mix of his career, his personal relationships, and his intellectual pursuits.
Posted by Dan Agonistes at 2:20 PM 0 comments
Saturday, July 10, 2004
More on Batting Order
From time to time I've criticized Dusty Baker for his lineup construction and he's now switching things up in an attempt to perk up the struggling offense (5 total runs during the current 5 game losing streak). In fact, in yesterday's 6-1 loss to the Cardinals weak hitting Rey Ordonez batted second. While I still think that's a mistake I was interested to read some lineup analysis done by Pete Palmer and John Thorn in their 1984 book The Hidden Game of Baseball. I bought a used copy on Amazon this week, having never read the book.
In the chapter "The Book...and the Computer" Thorn and Palmer analyze the average production at various lineup positions in both leagues from 1969-1971 which produced 4.141 runs per game. They then discuss how they used a computer simulation to test various lineups to see which produced the most runs. What they found was that a maximal number of runs could be score, 4.154 per game, when the traditional order was changed to 1-3-4-5-6-2-7-8-9. Since this equates to only 2 runs over the course of a season it seems to have little effect. In fact, the worst order (9-8-7-2-1-6-5-4-3) which no manager would ever employ produced 4.003 runs, a difference of 24.5 runs over the season. As a result Thorn and Palmer conclude that "All the time managers put into masterminding a winning lineup is so much thumb twiddling, and they are hereby granted an additional hour's sleep a night."
While I don't disagree with their analysis it still seems reasonable that a manager construct his lineup in descending order with "table setters" first, "all around hitters" second, and "runner advancers" last. The other factor to consider is that each spot higher in the order will garner an additional 18 plate appearances over the course of a season. As a result, hitting someone like Ordonez 2nd instead of 8th over the course of a full season gives him 108 more plate appearances. But in the end this analysis probably shows that rather than lineup construction, having a productive hitter at each position is vastly more important in scoring runs - especially in the National League where one or two weak hitters in addition to the pitchers creates a situation where over a third of your offensive innings are poisoned with weak hitters.
And speaking of weak hitters, the Cubs offensive woes continued today in a 5-2 loss to the Cardinals. One of the things that is particularly frustrating about watching the Cubs is how frequently they fail to score runners that reach base. In a discussion brought to my attention by my father-in-law you can rank teams by their efficiency in bringing runners around to score. A quick and dirty way to tabulate this "Run Scoring Efficiency" is:
RSE = (R-HR)/(H+BB-HR)
In other words this formula gives a rough indication of how effective a team is in being able to bring runners in to score. What this formula lacks is how often a team can score without the aid of a homerun since even though homeruns are subtracted from both the numerator and the denominator the runs component still includes runners who reach base and then subsequently score on homeruns. As of last Thursday here were the top 10 worst teams in the majors.
Montreal Expos NL 0.257
Seattle Mariners AL 0.286
Florida Marlins NL 0.294
Los Angeles Dodgers NL 0.298
New York Mets NL 0.301
Arizona Diamondbacks NL 0.304
Milwaukee Brewers NL 0.305
Chicago Cubs NL 0.306
San Diego Padres NL 0.310
Cincinnati Reds NL 0.310
If data were available to calculate the more correct version I'm sure the Cubs would rank at or near the top because of these teams they've hit the most homeruns (107). Another rough indication is what percentage of the team's runs are the direct result of a homerun calculated by dividing homeruns by runs scored. Here are the top 10 in that list as well.
Chicago Cubs NL 0.275
New York Yankees AL 0.275
Texas Rangers AL 0.274
New York Mets NL 0.271
Montreal Expos NL 0.266
Chicago White Sox AL 0.264
Philadelphia Phillies NL 0.257
Los Angeles Dodgers NL 0.256
Cincinnati Reds NL 0.246
Arizona Diamondbacks NL 0.238
Here the Cubs rank at the top and once again a better statistic would account for runners on base when a homerun was hit (I recently heard that the Cubs ranked first with 47% of their offense coming from homeruns but I don't have a complete list). Of course it helps if your team hits alot of homerun which the Cubs do and the Expos don't but still it shows how one-dimensional the Cubs offense is right now since they rank 22nd is on base percentage, 28th in stolen bases, and 10th in strikeouts.
Posted by Dan Agonistes at 8:37 PM 0 comments
Thursday, July 08, 2004
The Rantings of Michael Moore
This should be required reading for anyone sucked into seeing Fahrenheit 911. I've not seen the movie, only clips and an interview or two with Moore. I put the movie in the same intellectual category as alien abductions, the grassy knoll shooter, the Clinton Files, the CIA marketing drugs in the inner city, and the belief that O.J was innocent.
Posted by Dan Agonistes at 3:30 PM 0 comments
Bottom of the Order Analysis
A week or so ago I was watching an Astros game on ESPN when David Justice, former player and the analyst on the broadcast, began talking about Roger Clemens. In particular he noted that Clemens had recently said that 1) the inclusion of the pitcher in the lineup made pitching much easier in the National League and that 2) pitching to the 7 and 8 hitters in the National League was much easier than pitching to the 8 and 9 hitters in the American League.
Although I wasn't suprised by the former statement I was by the latter. I was skeptical of Justice's comment since my reasoning had always been that with the inclusion of the pitcher National League teams would generally prefer better hitting over defense in the remaining 8 positions. I then assumed that Clemens likely perceived the 7 and 8 hitters as weaker since he was able to pitch around them more frequently in order to get to the pitcher. Of course, the other side of the coin is that NL teams play in a more restrictive run environment and so are more prone to choose good defense over good offense at shortstop, second base, and center field.
To try and put together some numbers to answer the question I turned to Retrosheet. In less than an hour over lunch I did the following:
1. Downloaded the event files (play-by-play data files) for the AL and NL for 1992 (the most recent year available)
2. Generate comma-delimited files using the BEVENT.exe utility also on the site
3. Take the CSV files and loaded them into a SQL Server database on my laptop
4. Run a few simple queries to see how various positions in the batting order performed
What I found is that from this data (again, only for 1992) it appears that Justice may be on to something although the differences are not monumental. In fact, it could be argued that since the NL numbers likely include many instances for the 8 hitter in particular of being pitched around, the NL numbers are at least on a par with the AL. On the other hand, the number of walks drawn is not significantly different. It should be noted that on base average (OA) was calculated without the intentional walks (IBB) added in.
This then led me to consider how other positions fared and I was able to tweak my queries a bit to get the second data set. Once again nothing earth shattering here although the NL 3 and 4 hitters outperformend the AL 3 and 4 hitters which may indicate that the AL lineups have more balance.
So here it is:
AB H TB BB IBB BA SA OA OPS
AL 8-9 15670 3912 5324 1391 53 0.250 0.340 0.311 0.651
NL 7-8 13774 3292 4624 1075 233 0.239 0.336 0.294 0.630
AB H TB BB BA SA OA OPS
AL 7-8-9 23934 5975 8366 2131 0.250 0.350 0.311 0.661
NL 6-7-8 21030 5127 7350 1635 0.244 0.350 0.298 0.648
AL 1-2 18531 5028 7124 2031 0.271 0.384 0.343 0.728
NL 1-2 15883 4325 5930 1546 0.272 0.373 0.337 0.710
AL 3-4 17858 4767 7648 1768 0.267 0.428 0.333 0.761
NL 3-4 15050 4141 6601 1602 0.275 0.439 0.345 0.783
AL 5-6 16824 4236 6564 1850 0.252 0.390 0.326 0.716
NL 5-6 14617 3695 5617 1224 0.253 0.384 0.311 0.695
Posted by Dan Agonistes at 12:19 PM 0 comments
Wednesday, July 07, 2004
Woeful Offenses
The lack of offense the Royals have exhibited in recent weeks is now bordering on the unbelievable. After being shut out tonight 12-0 by the Twins for the third straight night the Royals are now on a 1-12 streak during which they've scored 27 runs (2.08 per game) and given up 91 (7 runs per game). The Royals have also now scored in only 2 of their last 45 innings. Overall, the Royals are now second to last in the AL in offense with 340 runs scored in 82 games (4.15 runs per game) leading only the Mariners at 336 runs.
Speaking of woeful offenses, the Cubs are also now scuffling having scored 2, 0, 2, and 0 runs in their previous 4 games. All their hitters look terribly impatient and are not hitting the few strikes they do swing at. Meanwhile they entered tonight's game 1 game in front in the Wild Card race and 5 games behind St. Louis. As I type this St. Louis is about to win again and the Dodgers are beating up on the Diamondbacks which will pull them even in the Wild Card and put them 6 games behind the Cards.
Both teams seem to be limping to the break.
Posted by Dan Agonistes at 8:58 PM 0 comments
Pocket PC Notification
One of the interesting functionalities of the Pocket PC is its Notification API. Unfortunately for .NET Compact Framework developers for now this API is in managed code only. As a result, a developer could use the OpenNETCF Smart Device Framework which contains a Notification class. However, if you don't wish to download and reference the entire SDF you could create a wrapper in the Compact Framework to add notification bubbles to your applications. Just such a class was written in C# by Seth Dempsey of the CF team and then posted by Gokhan Altinoren on the web. Well, here is the class rewritten in VB .NET.
Option Strict On
Imports System.Runtime.InteropServices
Imports Atomic.CF.InteropServices
Namespace Atomic.CF.PocketPC
Public Class Notification
#Region "Private Properties"
Private m_clsid As Guid
Private m_baseID As Integer
Private m_NotificationCount As Integer
#End Region
#Region "API Declarations"
'Default system icons
'private const System.Int32 MB_ICONINFORMATION = 0x00000040
'Notification priority'
'bubble shown for duration, then goes away
Private Const SHNP_INFORM As Integer = &H1B1
'no bubble, icon shown for duration then goes away
Private Const SHNP_ICONIC As Integer = &H0
'Notification update mask
Private Const SHNUM_PRIORITY As Integer = &H1
Private Const SHNUM_DURATION As Integer = &H2
Private Const SHNUM_ICON As Integer = &H4
Private Const SHNUM_HTML As Integer = &H8
Private Const SHNUM_TITLE As Integer = &H10
'Flags
'For SHNP_INFORM priority and above, don't display the notification
'bubble when it's initially added the icon will display for the
'duration then it will go straight into the tray. The user can
'view the icon / see the bubble by opening the tray.
Private Const SHNF_STRAIGHTTOTRAY As Integer = &H1
'Critical information - highlights the border and title of the bubble.
Private Const SHNF_CRITICAL As Integer = &H2
'Force the message (bubble) to display even if settings says not to.
Private Const SHNF_FORCEMESSAGE As Integer = &H8
_
Private Structure SHNOTIFICATIONDATA
Public cbStruct As UInt32 'For verification and versioning
Public dwID As UInt32 'Identifier for this particular notification
Public npPriority As UInt32 'Priority
Public csDuration As UInt32 'Duration of the notification
Public hicon As IntPtr 'Icon for the notification
Public grfFlags As UInt32 'Flags
Public clsid As Guid 'Unique identifier for the notification class
Public hwndSink As IntPtr 'Window to receive command choices
Public pszHTML As StringPtr 'HTML content for the bubble
Public pszTitle As StringPtr 'Optional title for bubble
Public lParam As UInt32 'User-defined parameter
End Structure
'Add
_
Private Shared Function SHNotificationAdd( _
ByRef shinfo As SHNOTIFICATIONDATA) As Integer
End Function
'Remove
_
Private Shared Function SHNotificationRemove( _
ByRef clsid As Guid, ByVal dwID As UInt32) As Integer
End Function
'Update
_
Private Shared Function SHNotificationUpdate( _
ByVal grnumUpdateMask As UInt32, _
ByRef shinfo As SHNOTIFICATIONDATA) As Integer
End Function
#End Region
#Region "Constructor & Destructor"
Public Sub New()
m_clsid = New Guid("{A6EF1E8E-5BC0-49d9-B03F-08BC163DADC8}")
m_baseID = 0
m_NotificationCount = 0
End Sub
#End Region
#Region "Private Methods"
Private Sub NotificationAdd(ByVal message As String, _
ByVal title As String, ByVal duration As Integer, _
ByVal hIcon As IntPtr, ByVal ID As Integer, ByVal clsid As Guid)
Dim shinfo As New SHNOTIFICATIONDATA
'Initialize and/or null-terminate the strings
If message Is Nothing Then message = "'"
If title Is Nothing Then title = ""
'Duration of the message
If duration <> 0 Then
shinfo.csDuration = Convert.ToUInt32(duration)
Else
shinfo.csDuration = Convert.ToUInt32(20)
End If
'ID
If ID <> 0 Then
shinfo.dwID = Convert.ToUInt32(ID)
Else
m_baseID += 1
shinfo.dwID = Convert.ToUInt32(m_baseID)
End If
'Guid
If clsid.Equals(Nothing) Then
shinfo.clsid = clsid
Else
shinfo.clsid = m_clsid
End If
'Fill the structure's remaining members
shinfo.cbStruct = Convert.ToUInt32(Marshal.SizeOf(shinfo))
shinfo.npPriority = Convert.ToUInt32(SHNP_INFORM)
shinfo.hicon = hIcon
Dim pTitle As New StringPtr(title)
Dim pHTML As New StringPtr(message)
shinfo.pszTitle = pTitle
shinfo.pszHTML = pHTML
Try
Dim err As Integer = SHNotificationAdd(shinfo)
If err <> 0 Then
Throw (New Exception("Invalid return from SHNotificationAdd"))
Else
m_NotificationCount += 1
End If
Catch ex As Exception
'Trace the error out
End Try
End Sub
'Remove a notification
Private Sub NotificationRemove(ByVal clsid As Guid, ByVal ID As Integer)
If m_NotificationCount > 0 Then
If ID = 0 Then ID = m_baseID
Dim err As Integer = SHNotificationRemove(clsid, Convert.ToUInt32(ID))
If err <> 0 Then
Throw (New Exception("Invalid return from SHNotificationRemove"))
Else
m_NotificationCount -= 1
End If
End If
End Sub
#End Region
#Region "Public Methods"
#Region "Add(...)"
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
Public Sub Add(ByVal message As String)
NotificationAdd(message, "", 0, IntPtr.Zero, 0, m_clsid)
End Sub
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
'/ Optional title for notification bubble.
Public Sub Add(ByVal message As String, ByVal title As String)
NotificationAdd(message, title, 0, IntPtr.Zero, 0, m_clsid)
End Sub
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
'/ Optional title for notification bubble.
'/ Duration of the notification.
Public Sub Add(ByVal message As String, ByVal title As String, _
ByVal duration As Integer)
NotificationAdd(message, title, duration, IntPtr.Zero, 0, m_clsid)
End Sub
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
'/ Optional title for notification bubble.
'/ The icon for the notification.
Public Sub Add(ByVal message As String, ByVal title As String, _
ByVal hIcon As IntPtr)
NotificationAdd(message, title, 0, hIcon, 0, m_clsid)
End Sub
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
'/ Optional title for notification bubble.
'/ Duration of the notification.
'/ The icon for the notification.
Public Sub Add(ByVal message As String, ByVal title As String, _
ByVal duration As Integer, ByVal hIcon As IntPtr)
NotificationAdd(message, title, duration, hIcon, 0, m_clsid)
End Sub
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
'/ Optional title for notification bubble.
'/ Duration of the notification.
'/ Identifier for this particular notification.
Public Sub Add(ByVal message As String, ByVal title As String, _
ByVal duration As Integer, ByVal messageID As Integer)
NotificationAdd(message, title, duration, IntPtr.Zero, messageID, m_clsid)
End Sub
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
'/ Optional title for notification bubble.
'/ Duration of the notification.
'/ Unique identifier for the notification class.
Public Sub Add(ByVal message As String, ByVal title As String, _
ByVal duration As Integer, ByVal clsid As String)
m_clsid = New Guid(clsid)
NotificationAdd(message, title, duration, IntPtr.Zero, 0, m_clsid)
End Sub
'/
'/ This function adds a notification (asynchronously) to the notification tray.
'/
'/ HTML content for the notification bubble.
'/ Optional title for notification bubble.
'/ Duration of the notification.
'/ Identifier for this particular notification.
'/ Unique identifier for the notification class.
Public Sub Add(ByVal message As String, ByVal title As String, _
ByVal duration As Integer, ByVal messageID As Integer, ByVal clsid As String)
m_clsid = New Guid(clsid)
NotificationAdd(message, title, duration, IntPtr.Zero, messageID, m_clsid)
End Sub
#End Region
#Region "Remove(...)"
'/
'/ This function removes a notification.
'/
'/ The class of the notification to remove.
'/ The unique identifier of the notification to remove.
'/ Do not set the value of this parameter to 0 that option is not implemented.
'/ If the value of this parameter is set to 0, the function will return an
'/ error.
Public Sub Remove(ByVal clsid As String, ByVal ID As Integer)
NotificationRemove(New Guid(clsid), ID)
End Sub
'/
'/ This function removes a notification by ID. The value of the guid property
'/ will be used as the class of the notification.
'/
'/ The unique identifier of the notification to remove.
'/ Do not set the value of this parameter to 0 that option is not implemented.
'/ If the value of this parameter is set to 0, the function will return an
'/ error.
Public Sub Remove(ByVal ID As Integer)
NotificationRemove(m_clsid, ID)
End Sub
'/
'/ This function removes a notification by class. The value of the ID property
'/ will be used as the ID of the notification.
'/
'/ The class of the notification to remove.
Public Sub Remove(ByVal clsid As String)
NotificationRemove(New Guid(clsid), 0)
End Sub
#End Region
#Region "Others"
'/
'/ This function removes the last notification added, if any.
'/
Public Sub RemoveLast()
NotificationRemove(m_clsid, 0)
End Sub
#End Region
#End Region
#Region "Public Properties"
'/
'/ A number when tagging notifications with an ID. If no ID
'/ specified during an Add(), ID property is incremented by one, used as ID
'/ and saved back into ID property.
'/
Public Property ID() As Integer
Get
Return m_baseID
End Get
Set(ByVal Value As Integer)
m_baseID = Value
End Set
End Property
'/
'/ A String that contains a GUID
'/ If this property is not set,
'/ {A6EF1E8E-5BC0-49d9-B03F-08BC163DADC8} is used as GUID.
'/
Public Property clsid() As String
Get
Return m_clsid.ToString()
End Get
Set(ByVal Value As String)
m_clsid = New Guid(Value)
End Set
End Property
#End Region
End Class
End Namespace
In rewriting this code in VB .NET one of the major differences is that the C# code
used the unsafe and fixed keywords to handle string pointers within the notification
structure. These keywords are not available in VB and so a managed string pointer
class was created (as documented in our whitepaper on MSDN) as shown here.
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Namespace Atomic.CF.InteropServices
Public Class Memory
_
Private Shared Function LocalAlloc(ByVal uFlags As Integer, _
ByVal uBytes As Integer) As IntPtr
End Function
_
Private Shared Function LocalFree(ByVal hMem As IntPtr) As IntPtr
End Function
_
Private Shared Function LocalReAlloc(ByVal hMem As IntPtr, _
ByVal uBytes As Integer, ByVal fuFlags As Integer) As IntPtr
End Function
Private Const LMEM_FIXED As Integer = 0
Private Const LMEM_MOVEABLE As Integer = 2
Private Const LMEM_ZEROINIT As Integer = &H40
Private Const LPTR = (LMEM_FIXED Or LMEM_ZEROINIT)
' Allocates a block of memory using LocalAlloc
Public Shared Function AllocHLocal(ByVal cb As Integer) As IntPtr
Return LocalAlloc(LPTR, cb)
End Function
' Frees memory allocated by AllocHLocal
Public Shared Sub FreeHLocal(ByVal hlocal As IntPtr)
If Not hlocal.Equals(IntPtr.Zero) Then
If Not IntPtr.Zero.Equals(LocalFree(hlocal)) Then
Throw New Win32Exception(Marshal.GetLastWin32Error())
End If
hlocal = IntPtr.Zero
End If
End Sub
' Resizes a block of memory previously allocated with AllocHLocal
Public Shared Function ReAllocHLocal(ByVal pv As IntPtr, _
ByVal cb As Integer) As IntPtr
Dim newMem As IntPtr = LocalReAlloc(pv, cb, LMEM_MOVEABLE)
If newMem.Equals(IntPtr.Zero) Then
Throw New OutOfMemoryException
End If
Return newMem
End Function
' Copies the contents of a managed string to unmanaged memory
Public Shared Function StringToHLocalUni(ByVal s As String) As IntPtr
If s Is Nothing Then
Return IntPtr.Zero
Else
Dim nc As Integer = s.Length
Dim len As Integer = 2 * (1 + nc)
Dim hLocal As IntPtr = AllocHLocal(len)
If hLocal.Equals(IntPtr.Zero) Then
Throw New OutOfMemoryException
Else
Marshal.Copy(s.ToCharArray(), 0, hLocal, s.Length)
Return hLocal
End If
End If
End Function
End Class
Public Structure StringPtr
Private szString As IntPtr
Public Sub New(ByVal s As String)
Me.szString = Memory.StringToHLocalUni(s)
End Sub
Public Overrides Function ToString() As String
Return Runtime.InteropServices.Marshal.PtrToStringUni(Me.szString)
End Function
Public Sub Free()
Memory.FreeHLocal(Me.szString)
End Sub
End Structure
End Namespace
The end result is the ability to add the following lines of code to your application
in order to show a notification bubble.
Dim n as New Atomic.CF.PocketPC.Notification()
n.Add("My Message","My Title",3,hIcon)
Where 3 is the duration of the bubble and hIcon is a pointer to an icon extracted
from the executable typically using the ExtractIconEx unmanaged function.
Posted by Dan Agonistes at 9:48 AM 2 comments
Tuesday, July 06, 2004
Sabermetrics and the Kansas City Royals Baseball Academy
As I've mentioned before in this space one of the benefits of being a member of SABR is receiving the The National Pastime: A Review of Baseball History published each year by SABR and which includes articles written by SABR members. I've just received my copy and was delighted to read an article by Richard Peurzer titled "The Kansas City Royals Baseball Academy". In this post I'll summarize the article and then provide a little analysis from a sabermetric perspective.
In the article Peurzer recounts the history of the academy, the brainchild of late Royals owner Ewing Kauffman who established the franchise in Kansas City in 1969 and opened the academy in Sarasota Florida in 1970. The 121 acre facility included five fields, dorms, offices, classrooms, and a swimming pool and was staffed with a combination of ex-big leaguers, college coaches, and experts outside of baseball in fitness and weight lifting, track, ophthalmology, and psychology. Syd Thrift, who was already employed by the Royals scouting department was tasked with running the academy.
Kauffman established the academy because "he was disenchanted with the conservative nature and the resistance to change found in the baseball establishment." He wanted to apply innovation to baseball in the same way he applied it in his business ventures with Marion Labs where organizations used technology to continually refine their practices. Indeed, the establishment of the academy was quite revolutionary as Peurzer compares it to other improvement efforts in the history of the major leagues, none of which were so extensive or required so much investment.
What most interested me was the recruiting methodology used. It was the goal of the academy not primarily to refine baseball skills but to reach untapped talent. In fact, it was Kauffman's belief that "an athlete did not necessarily have to play baseball all his life in order to be a good baseball player" and that there were lots of athletes who were not scouted or that never played much baseball. And in that vein the tryouts that were held across the country selected 43 out of 7,682 candidates to be the first class at the academy. In particular, four physical attributes (and several psychological ones) were used to make the selections:
These attributes were apparently arrived at by testing 150 players, many of whom were already within the Royals organization. These 43 athletes from 23 states were then sent to the academy for 10 months during which they would play 150 games against other pro teams in exhibitions as well as the Gulf Coast League. The players would receive detailed instruction (and attend classes at a local junior college) every day. Some of the innovations created by the academy included the use of pitching machines for both hitting and fielding, weight and strength training using resistance techniques such as rubber bands, stopwatches, and visualization.
These innovations seemed to payoff in wins and losses as the first class from the academy went 40-13 in the Gulf Coast League, easily wining the championship. In particular the team stole 103 bases in 119 tries, 48 more stolen bases than the second best team. Despite the apparent success the second academy class was scaled down to 20 players and supplemented with Royals minor leaguers for short stints. Still, the team went 41-22 and stole 161 bases. The third class included only 14 players and the team went 27-28, however still leading the league in steals by a large margin. The academy was shut down probably both because of its economic impact, it cost $1.5M to build and $700,000 annually to maintain, and the fact that the old school baseball people running the Royals such as manager Charlie Metro just didn't believe in the concept and coveted the money "which could have been used in the traditional player-development programs."
Analysis
In the end it seems to me the academy was a success in two primary ways. First, it graduated 14 players to the majors out of the 77 players, most of whom would never have even been drafted. That seems a pretty high percentage when compared with the draft and includes Frank White, Rodney Scott, U.L. Washington, and Ron Washington.
Second, the academy was clearly successful in concentrating on advanced training techniques such as weightlifting and some innovative techniques that are still used today. For example, it can be argued as Peurzer does that the academy's focus on base stealing as a skill helped start the revolution in base running in the late 1970s and 1980s. For example, at the academy they determined that an average runner could take a 12-foot lead off first and a 27-foot lead off second and also used stopwatches to time the delivery of pitchers and release times of catchers to calculate the probability of successfully stealing bases. This clearly contributed to the academy teams outstanding base stealing success. Kauffman's analysis that technology was not being used effectively in baseball was largely born out.
On a higher level though the academy failed in two ways as well. First and most importantly, although the academy graduated 14 players to the majors in just 3 years, the methodology of selection, concentrating on raw athleticism and untapped talent in inner cities, made it a forgone conclusion that those graduates would likely be light-hitting middle infielders who were good base stealers and not offensive producers. This is the case since the academy was (perhaps unwittingly, Peurzer doesn't address this) selecting for the positions that required the most athleticism and the fewest refined skills. So while Kauffman was correct that applying technology could make a difference in baseball, it was applied at the academy without the critical information as to what actually wins baseball games. The sabermetric revolution started to pick up speed at roughly this same time with the publication of The Baseball Encyclopedia although it would be almost a decade before the publication of The Hidden Game of Baseball by Pete Palmer and John Thorn and wide distribution of Bill James' Baseball Abstracts and a further twenty years before big league GMs would start applying some of the principles as documented in Moneyball. As a result, the academy teams were basically one-dimensional teams (although still successful overall). And so lacking this information, the academy probably would not have been successful in producing top-level major league players.
Second, the academy failed because it didn't convince the entrenched baseball establishment to adopt its approach directly. Kauffman remained a believer and later stated "that he believed that the Royals would have been better off keeping the Academy alive." The failure to make believers out of the front office might be linked to the fact that no super prospect was immediately found, background racism based on the makeup of the classes, or simply to what Charlie Metro called the "crazy instruction". In any case this really can't be laid at the feet of the academy since baseball has historically and continues to be an extremely conservative industry.
Posted by Dan Agonistes at 4:15 PM 2 comments
Offensive Woes Continue
Oh boy! Since Carlos Beltran last appeared on the field for the Royals on June 24th, the Royals are 1-10 having scored just 27 runs (2.45 per game) while their opponents have scored 75 (6.82 runs per game). During this period Joe Randa, David DeJesus and Mike Sweeney have all been sidelined for part of the time as well (they now have 10 players on the disabled list and have used 47 players this season - a new major league record before the All-Star break!). As a result the lineup is packed with weak hitters with no extra base power who don't get on base. Yikes. In an earlier post I said that the Royals would probably come back to win around 75 games. For them to do that they'll need to go 46-37 the rest of the way. With this offense combined with the poor pitching and defense that is unbelievably unlikely.
With Sweeney now out for 4 days and counting it would have been a good time to call up Calvin Pickering. However, the Royals have made clear that they don't feel Pickering is a bona-fide prospect any longer at 29 years of age. Pity - because he's a better hitter than anyone else on the team and he's earned the right to be in KC with his performance in Omaha.
So what the Royals did do this week was tade for former prospect Ruben Mateo from the Pirates for cash and send Byron Gettis back to the minors. Mateo is a "tools guy" but unfortunately he's never used his tools at the major league level. He had a good stint at Louisville (AAA) last year hitting .327 with a .408 OBP in half a season but has never shown any patience at the big league level drawing only 46 walks in over 800 plate appearances. If he can find some patience the Royals are the one team he could stick with. As for Gettis (24), I'm glad he's being sent back down since he wasn't getting any playing time (only 39 at bats since being called up on May 27th).
Posted by Dan Agonistes at 11:33 AM 0 comments
Soccer vs. Baseball
Interesting article on the socialism of American sports such as baseball and the capitalism of European soccer.
Posted by Dan Agonistes at 11:29 AM 0 comments
Friday, July 02, 2004
Cubs on the Rise
I haven't written anything recently about the Cubs. Initially it was because I was discouraged with how the team was performing and all the injuries and recently I've just been too busy. Anyway, heading into the July 4th weekend series against the White Sox (which I'll be enjoying with family in Iowa) the Cubs are holding their own, second place in the division 3 games behind the Cardinals.
The Cubs had a good stretch in June winning 9 of 10 against their stiffest competition of the season (Angels, A's, Astros) and going 15-12 for the month. Add to that the fact that both Mark Prior and Sammy Sosa returned from injuries and there is good reason to be optimistic. What is most pleasing for Cubs fans, however, is:
Kerry Wood will make a start at Iowa next week and then they may be back to full strength. I'd still like to see the Cubs find a shortstop who can hit a little so they don't have to play Rey Ordonez. They could also move Grudz to short since Walker's bat is missed when he's out of the lineup.
One of the interesting aspects of this season is that the Cubs will be finished playing the Cardinals before the end of July and the Astros by the end of August. That means that games against Milwaukee, Pittsburg, Cincinnati, Florida, and the Mets in August and September will tell the tale for the Cubs.
Posted by Dan Agonistes at 12:34 PM 0 comments
Meet the 2005 Royals
Well, since the season is a bust it's time to look at 2005. Here's what I think the Royals should do now to prepare:
So you're lineup would look as follows:
Dejesus CF
Graffanino 2B
Sweeney DH
Pickering 1B
Harvey LF
Brown RF
Berroa SS
Bautista 3B
Buck C
And then Gettis would be your 4th outfielder. While this lineup won't score that many runs and its not any better defensively it can't really be worse than what we've seen since the Beltran deal.
On another subject I scored last night's 3-2 loss to the Orioles. I was quite impressed with Zack Grienke as it was the first time I'd seen him live. He really changed speeds well, located his fastball, and in one at bat threw a 93mph fastball and a 63mph curveball. He's the real deal. Not sure if he simply got tired but his location was bad in the 7th when Palmeiro took him deep and then he gave up back to back doubles.
Posted by Dan Agonistes at 7:43 AM 0 comments
Thursday, July 01, 2004
Stat Guy
Great post by Ron Hostetter on the Royals where he points to The Stat Guy columns in the KC Star. As noted in the column the Royals defense has been poor as evidenced by their Defensive Efficiency Rating (DER) (the percentage of balls put in play that were turned into outs) and Zone Rating (percentage of balls hit into certain zones that made into outs). To pile it on it should be noted that they're also third from the bottom in giving up unearned runs with 50 (half as many as the Devil Rays - the team being compared to the Royals in the Stat Guy column) behind only Arizona (51) and Boston (60) and have committed 65 errors. This was brought to my attention vividly yesterday while scoring the game as they gave up 4 unearned runs with three errors.
As of today the runs scored and runs allowed looks as follows:
RS RA ER
Royals 328 418 368
Rays 344 365 340
This gives the Royals a pythagorean winning pct. of .381 and the Rays .470 when in actuality the Rays are at .507 and the Royals at .387. So the Devil Rays have also gotten more out of less than the Royals have. All other things being equal (which they're not since luck plays a role) it seems that team speed is the X-factor in this case allowing a team to take better advantage of misplays and errors that squeek out a game every now and then, something the Royals are definitely lacking but that the Rays have. However, even taking into account only earned runs the Royals still have a deficit of 44 runs with the Rays (16 on offense and 28 on defense) which makes a bigger difference than you might think since winning percentage varies with the square of runs scored per the pythagorean formula. So while I agree that the Royals defense is bad (particularly in the outfield corners and the right side of the infield) the hitting and pitching have been equally as bad ranking near the bottom in most categories and just as a good team is more than the sum of its parts (e.g. the 1998 Yankees), a team that is bad in all aspects is less.
Posted by Dan Agonistes at 8:49 AM 0 comments