Auction Drafts, ottoneu, and you

Tonight, two leagues had long delays with their auction drafts. I want to write about what happened, the full context around the circumstances, and how it will be fixed going forward. I think it is very important to be transparent about these issues to show how ottoneu is going to improve to address these concerns.

At 3:07pm ET, I received this tweet:

I am currently in Copenhagen, Denmark on vacation from my day job, and my data plan is wonky to say the least. I received tweets regarding this issue for the next hour:

I also received a number of emails during this time period.

I happened to see this last tweet when opening my Twitter client on my phone. Up to this point in the trip, I received push notifications upon new tweets, but this time I didn’t see anything until I happened to open my phone’s client. As soon as I saw these tweets, I rushed back to the apartment I am staying in and spent about 2 minutes debugging the issue and resolving it.

There are a number of questions about this scenario:

  1. Why was the issue not acknowledged earlier?
  2. How was it fixed so quickly when it was open for so long?
  3. Why are there so many issues with auction drafts on ottoneu?

I will address each of these issues in order. Of course, if you have other concerns, I’m more than happy to address them over email or in the comments.

1. Why was the issue not acknowledged earlier?

I am in Denmark right now, for my first vacation since July of last year. Unlike last July or the previous vacation in November 2012, my laptop was not with me the entire trip and I did not put someone else in charge of any issues in my absence. This is also my first trip during the peak ottoneu months, which are February and March, when all the auction drafts occur. Finally, while I expected Twitter push notifications to my phone, I did not receive any this evening.

Solution:

While ottoneu does not make very much money at all, what little I do make this year will go towards a small laptop that I can keep on my person throughout February and March. I will also be more conscientious of vacations during this time, and much closer to this or some computer during this time, until ottoneu makes enough money to warrant a second employee. There is no excuse for this not being addressed faster during such a sensitive time.

2. How was it fixed so quickly when it was open for so long?

Plenty of ottoneu issues are actually quite simple, and only come up when some code I hastily write is pushed into production. In this case, I did a big rewrite of the auction draft in the offseason to try and improve performance. Part of this was to introduce redis to the ottoneu technology stack. Redis comes highly recommended from the aforementioned day job, and I have some experience with it but I made a couple of fairly simple mistakes. These cropped up quickly when faced with production load, and I was able to sort them out and resolve them quickly.

Solution:

See the above – faster response time will almost always mean a faster resolution. A longer-term outlook has a better test environment and more robust testing, but honestly that is a luxury right now.

3. Why are there so many issues with auction drafts on ottoneu?

While no one has straight-up asked me this question, this is a question I ask myself often. There are basically two competing interests:

1) auctions are hard to schedule and when they are scheduled, everyone wants to run their auction.
2) auctions are computationally difficult to keep real-time, and they are also very sensitive to errors, so there should be 100% confidence in live auction drafts when they are run.

There are two solutions that I am capable of: the first is rewriting large portions of the auction draft code to use more redis and less database. Database bad, cache good. The second is to invest in more servers. I plan on doing the former extensively, as talking to a few colleagues indicates that this will increase capacity considerably. I’ve already done this a bit, and I hope to do this more.

I’ve already increased the number of auction drafts that can run at a single time by 50% over last year. I’m hoping to pop it up to a full 100% and then start exploring more server capacity. So this is a “stay-tuned”, but is also a catch-22, because like I said earlier, ottoneu really doesn’t make much money at all (it was a net-loss the last two years even without any full-time employees). So until ottoneu truly has enough users to afford more server capacity, more efficient code is the best way forward. Like I said, I will continue to work towards this end to make this a reality.

That is the full situation around the issue tonight and the overall auction draft issue. I’m back home in 2 days and will be vigilant on any draft issues through April, when capacity drops considerably and we return to the predictable, boring, wonderful grind of a new baseball season. I hope this has been helpful, and please let me know if you have any further questions or concerns.

Going in to 2014

Man, I forgot about this place. No time for apologies, let’s get into it.

It is February 19, 2014. There is a high likelihood of a lot of new users coming to ottoneu in the next month before the season starts, but let’s look at where things are now, shall we?

  1. 1917 active teams.
  2. 25 active prize leagues and 123 active non-prize leagues.
  3. 401,293 player transactions, spending $538,395 in ottoneu cap.

I’m going to throw a parade when we get over $1mil in cap spent. There are a few other important things to note, especially in regards to the now woefully outdated first 30 days post. My users remain incredibly patient and smart and understanding. The number of “shit is broken” emails have decreased to a trickle – ottoneu has become a relatively stable (KNOCK ON WOOD) platform! Even the auction drafts are performing smoothly, to the point where most of the emails about them are for really interesting feature enhancements, not “man this was slow, give me some money back.”

So, that is the basic state of things today. Now, what are the big things on the horizon? Well, there are 3 big initiatives this year, each worthy of its own series of posts:

  1. Rewriting the stats backend – after determining that a soft innings cap (and thus allowing pitcher streaming on the last day of the season) was a double-edged sword for owners and self-balancing, there is a massive opportunity for performance improvements and general efficiency with ottoneu’s stats backend. This project is ongoing and should be wrapping up in the next couple of weeks. It should be completely transparent to users, and it has to get done before the season starts. So, that’s priority #1.
  2. A better lineup page experience – the lineups page is fine, it gets the job done. But during the long baseball season, this is where a lot of time is spent. It also is the basis for the off-season roster organizer. More stats, splits, and a smoother experience swapping players in and out will go a long way towards making ottoneu feel world-class.
  3. A full redesign – while I may have sentimental attachment to the Waste Management colors and my crazy-good (read: not) logo, I think ottoneu can look significantly better. This project is actually really close to being done, but probably won’t be released until the All-Star break, just to tighten everything up and not get in the way of the top two priorities. The new logo looks boss.

That is where things stand going into this season. I plan on keeping a loose development blog here, so feel free to comment here, tweet at me, hit me up on Facebook, or just plain email me (help at ottoneu dot com). I cannot wait for baseball. Good luck this season!

Raising Money

Sorry about the recent lack of posts.  Things always get quiet towards the end of the year, and I have been traveling and coding and coding and traveling non-stop the last few weeks.  Hopefully Geoff and I will get things going again as baseball season nears.

A few days ago, my friend Zach and I had a discussion over email about raising funding for internet startups.  The conversation was spurred by this article from the Economist, discussing a possible pending tech bubble.  Zach argued that the bubble was clear to him when someone, somewhere decided that the reported $6 billion bid on Groupon by Google was not enough money and called the deal off.  My counter point or more accurately put continuation of the conversation is below, slightly edited.

[T]o me the ‘bubble’ aspect is that a lot of pointless things (as the economist points out) are getting funded.  Like, pointless things.  gimmicky neat tech demos are getting funded.  And to me that is the main point of irrationality.

[It] sounds like irrationality is closing in on two fronts though.  one on the “spray and pray” front where angels will fund idiotic ideas, and another on the high end where companies are being overvalued.  the former seems more pervasive, and the latter seems bubble-y.

Part of this has to do with comfort.  Stupid-to-less-than-stupid-to-reasonable-but-unproven ideas should all be bootstrapped.  Instead, we have these idiots who are so afraid of eating ramen that they spend all their time and effort on figuring out how to raise money instead of how to build a true business.  The raising money is the goal, because then you can make 80k a year doing your own stupid thing and it’s living the dream.

I interviewed with that Sunfire place again last night.  the woman I spoke with asked me if i wanted to raise money.  I said preferably no, but i could see reasons to.  And i said the only reason I would was if I was not at enough users to pay for itself but enough users that I saw a future in the business.   And she made a reality-based statement that depressed me – it’d be really hard to raise money if I don’t have the numbers I was hoping for – its easy if you get huge amounts of growth, of course.  But I was like – wait, if i have enough users, why would I ever raise money?

And part of that is the thing too.  If you don’t have ANY proof, you’re in a better spot than if you have numbers that aren’t stellar.  And in a way, that is the investor needing comfort too – either the comfort of the irrational kool-aid or the comfort of stellar numbers.  Less than awesome numbers on a launched product that might require (gasp) work was looked at by the woman I was talking to, accurately, as a liability.

So, this is why I don’t want to raise money.  mostly because investors are risk-averse assholes.  And also because I like ramen.

Despite being one of the risk-averse assholes I called out in that email, Zach liked the response, and the more I think about it, the more I like it as well.  I understand the need to raise money even if your startup proves itself spectacularly – growth can always use more capital, etc, etc.  But there is a lot of weirdness in the money-raising world, and until I find some people who see things a bit more in line with how I see things, I don’t see myself actively pursuing funding.

The Solution? More Tables

I don’t know very much about database design.  I tried taking a course once in college but the professor scared me on the first class and I ended up dropping it, which I guess now that I write it out I regret.  What little I do know I have taught myself from both production examples from my previous jobs and just general experience.  That being said, there is one  rule that I’m slowly learning that I feel the need to record.  Whenever there is some sort of complication with storing or retrieving data in a relational database, the solution is always more tables.

Yesterday I was struggling with a problem.  If two teams agree to a trade involving a given set of players, all other trade proposals including those players should no longer be active.  For example, if Albert Pujols is involved in a trade that has been accepted, he shouldn’t be still out there in other trade proposals – we don’t want two or more teams concurrently accepting trades with Albert Pujols!

On its face, this seems like a basic enough problem, but the twist is my existing database schema.  It looks like this:
[cc lang=”mysql”](
ID int(11) NOT NULL auto_increment,
ProposalDate date NOT NULL,
ProposingTeam tinyint(4) NOT NULL,
TargetTeam tinyint(4) NOT NULL,
ProposingTeamPlayers varchar(30) NOT NULL,
TargetTeamPlayers varchar(30) NOT NULL,
ProposingTeamLoan int(11) NOT NULL,
TargetTeamLoan int(11) NOT NULL,
Accepted tinyint(4) NOT NULL default ‘0’,
Rejected tinyint(4) NOT NULL default ‘0’,
PRIMARY KEY (ID)
)[/cc]The problem here is that I’m storing “ProposingTeamPlayers” and “TargetTeamPlayers” as strings. So for each trade, I implode the array of players involved into a comma-delimited list. This is all well and good until you realize you want to search for all trade proposals involving a given player. The process then becomes:

  1. Find all trade proposals involving either team
  2. Get all players involved in said trade proposals
  3. Check if any of the players are involved in the just accepted trade
  4. If yes, then mark that trade proposal as rejected (which, implicitly, it is)

The solution to getting rid of this awful, slow code? Add a new table:[cc lang=”mysql”]TradeProposalID int(11) NOT NULL,
PlayerID int(11) NOT NULL,
TeamID int(11) NOT NULL,
PRIMARY KEY (TradeProposalID,PlayerID)[/cc]Then this query gives us what we want:[cc lang=”php”]$sql = “SELECT ID FROM TradeProposalsIndexTable JOIN TradeProposalsPlayersTable ON ID=TradeProposalID WHERE Accepted=’0′ AND Rejected=’0′ AND PlayerID=$playerID”;[/cc]Mark all those trades as rejected, and all done.

Without adding new tables, I had a mess trying to store multi-player trades in my database, and I had a hacky solution that clearly was not well thought out.  Add a table, remove those ProposingTeamPlayers and TargetTeamPlayers columns, and a multi-line complete mess of a solution turns into 2 elegant lines of SQL.

So we’re left with a simple rule to follow at all times: if you are getting confused by how to get or store data with your relational database, add some more tables.

First Pitch

We are now 4 days back from First Pitch: Arizona.  I can’t speak for Geoff, but for me, the conference was a rousing success.  If you had told me all the positive things that happened in Phoenix were going to happen before going, I would have gladly paid twice.  An overview:

  • Maybe not the father of fantasy baseball, but at least a pretty influential uncle, Ron Shandler is the real deal when talking about one of the game’s great minds.  He presented a new approach to fantasy baseball at the conference, one which is similar to my game in a number of ways.  We met (along with Geoff!) for a hour after he presented his game, and he came away with a very favorable impression of what I’ve been working on.  He even mentioned it as legit to the entire conference.  If that isn’t a strong endorsement, I don’t know what is.
  • Joel Henard at Baseball Prospectus Radio offered to interview me for his show.  Repeat: I was offered an interview.  About a fantasy baseball game.  From the guy who has interviewed real, actual GMs and baseball players.
  • Everyone, without exception, who got a taste of my full pitch was asking me things varied from “sounds awesome” to “when can I sign up?”
  • Joe Sheehan recognized me coming up an elevator and asked if I’d be around later at the Rising Stars baseball game or for poker later on.  Swoon.

The amazing thing about having people, real live people validate what you’re spending hours a day working on – what you’ve left a safe, comfortable job, to work on – is that it makes you forget everything else.  It just makes you want to f’n code the hell out of it.  So, I’ll say it again: let’s go.

What I’ve been up to, part 2

AVG BY BALL TYPE

Fly balls:

Ground balls (even though the OF looks silly here I think it makes sense – there really are three dead spots that sorta blend together on the fringes, one behind each defender):

Line drives:

Pop ups (no, I’m not changing the name of the Y-axis):

SLG BY BALL TYPE

Fly balls:

Ground balls:

Line drives:

Pop ups:

I really should merge pop ups with fly balls, but for now just merge them in your mind. Also, if you look really closely you’ll notice that fly balls and line drives extend out to 480 ft in the y direction, while ground balls and pop ups only go to 420. I’m going to re-run everything tonight, extending out to 500 ft (but probably won’t share those, unless someone asks).

Leaping

Much like Geoff, I haven’t checked in over here in far too long.  The last time I posted, I mentioned that I had given notice at my previous job and was going full time on the project that most of you know about already.  So it seems like that is as good a place as any to start.

While Geoff is working on an extreme research project, I am working on almost the opposite: a new consumer-facing fantasy sports service, ottoneu.  In the vein of Yahoo! Fantasy Sports, ottoneu will provide fantasy games for users, but with an emphasis on niche users and in-depth, hardcore games.  Without getting in to the details (and blowing any fun surprises that might be coming down the line), I can safely say a few things.

  1. The fantasy baseball product I am working on is unique and fun
  2. Working for yourself is fun and stressful
  3. It is incredibly rewarding to spend 100% of the day working on something that you are not only interested and invested in, but you truly enjoy

So I have leapt.  I am now the Founder and CEO of ottoneu, Inc.  Soon, I will be bringing you better fantasy sports – richer, more interesting, more engaging, and much, much more fun.  My goal here is to, without ruining any good surprises, take you along on the ride to launch day.

What I’ve been up to

So I haven’t posted here in much, much too long. But that doesn’t mean that I haven’t been doing things! Without any additional commentary, here are plots of balls hit by batted ball type (fly ball/ground ball/line drive/pop up) for 2007-2009. Note that to smooth the data, the count shown on the right is the number of balls within a 5 foot radius of that point. Also, I have not done any work yet to clean the data, so there are a few points here and there that don’t make much sense.

Fly balls:

Ground balls:

Line drives:

Pop ups:


Does strategy = talent?

Cliff Lee is dealing tonight: 9 Ks/0 BBs through 7 IP (and maybe more to come soon). No doubt he’s one of the best – if not the best – pitcher in the game at the moment. He’s throwing nasty pitches but also mixing them up effectively and hitting his spots. Now I think it’s clear to say that his pitch quality and precision are “talents.” Maybe more debatable is his pitch selection and general location – I’ll contend that it is a strategy, instead. Could he possibly be performing even more effectively if he had Greg Maddux in his ear calling pitches?

Lee is still really good by any measure – now 10 Ks/0BBs through 8.

This post has been revised on account of being written while highly distracted by baseball and after a few beers. It needs to be expanded upon anyway.