Answers.Body: <p>Collected data from the <a href="https://lichess.org/player/top/200/bullet" rel="nofollow noreferrer">top 100 bullet players in Lichess</a> using the <a href="https://berserk.readthedocs.io/en/master/usage.html#by-player" rel="nofollow noreferrer">berserk</a> module from <a href="https://lichess.org/api" rel="nofollow noreferrer">lichess api</a>.</p>
  <p>The function <code>client.games.export_by_player()</code> can give info about the games played by a player. This includes <code>createdAt</code> and <code>lastMoveAt</code> timestamps values from which we can calculate the duration of the game.</p>
  <p>Be noted that extracting game time duration through game clk info may not be appropriate because most of these players are pre-moving. Even if their clock is at 1s some players can still make some moves with their clock still at 1s.</p>
  <h2>I. Bullet games at TC 60+0</h2>
  <h4>Some figures</h4>
  <p>Bullet games from top 100 bullet Lichess players, each player has
  around 200 games at tc 60+0 less duplicates.</p>
  <pre><code>num data: 18125
  min   (s): 21
  max   (s): 200
  mean  (s): 103
  stdev (s): 32
  </code></pre>
  <h4>Overall distribution</h4>
  <p>There are games that are more than 120s due to pre-moves.</p>
  <p><a href="https://i.sstatic.net/eoWSw.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/eoWSw.png" alt="enter image description here" /></a></p>
  <h4>Resigned games</h4>
  <p>It peaks close to 100s.</p>
  <p><a href="https://i.sstatic.net/qOiVL.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/qOiVL.png" alt="enter image description here" /></a></p>
  <h4>Checkmates</h4>
  <p><a href="https://i.sstatic.net/NeMes.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/NeMes.png" alt="enter image description here" /></a></p>
  <h4>Time forfeit</h4>
  <p><a href="https://i.sstatic.net/3NSnL.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/3NSnL.png" alt="enter image description here" /></a></p>
  <h4>Draws</h4>
  <p><a href="https://i.sstatic.net/w3rco.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/w3rco.png" alt="enter image description here" /></a></p>
  <h4>Stalemate</h4>
  <p><a href="https://i.sstatic.net/TpULn.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/TpULn.png" alt="enter image description here" /></a></p>
  <h4>Overall result by game termination</h4>
  <p><a href="https://i.sstatic.net/c6qvQ.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/c6qvQ.png" alt="enter image description here" /></a></p>
  <h2>II. Bullet games at TC 30+0</h2>
  <p>Bullet games from top 100 bullet Lichess players at TC 30+0</p>
  <pre><code>num data: 6963
  min   (s): 21
  max   (s): 120
  mean  (s): 63
  stdev (s): 17
  </code></pre>
  <p><a href="https://i.sstatic.net/YudrG.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/YudrG.png" alt="enter image description here" /></a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-16T20:53:00.300Z
Answers.Text: How do premoves generate more time on the clock?
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-16T21:00:18.843Z
Answers.Text: I wonder if that has to do with the way the server accounts for latency. I've wondered the same thing while playing on lichess -- games that are both down to where each player has 1 to 2 seconds left seem to go a lot longer than the 2-4 seconds indicated by the clock.
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-16T21:06:45.093Z
Answers.Text: @L.ScottJohnson [Here's an example](https://www.youtube.com/watch?v=G2AMN9tHSB0&t=2324s) where I believe that happens. This is an 8s/0 game on both sides, and starts at the 38:44 mark. At the end of the game the players have a combined 3.9 seconds left, which is at the 39:07 mark. That means 12.1 seconds of in game time elapsed, but 23 seconds of real time!
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-16T22:16:26.400Z
Answers.Text: @Dargscisyhp Sure. But the question is formulated around clock time, not real time.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-16T22:20:12.020Z
Answers.Text: @L.ScottJohnson Probably the question is formulated under the assumption that clock time and real time are one and the same. Either way, both answers are interesting.
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-19T16:12:22.860Z
Answers.Text: Another factor, perhaps a bigger factor, in the discrepancy is that createdAt is not the time the game started. The added time from those gaps (between game creation and game start) likely dwarfs the accumulated from pre-moves latency. As an extreme example, the 1+0 game I tested with, which ended after 3 seconds, shows 40 minutes and 20 seconds elapsed from creation to last move.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-19T19:30:05.233Z
Answers.Text: 1+0, 40m+20s, that is weird, could you post the game id?
Answers.UserDisplayName: ferdy
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-19T21:10:34.640Z
Answers.Text: It's extreme length for a gap, but the gap existing is common. It's the difference between the time the game is created and the time the game begins. Reference test game: https://lichess.org/dotb5hRF
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-20T01:10:54.890Z
Answers.Text: That game is casual. Can you find a rated game having a weird elapse time? In my datasets I use rated games.
Answers.UserDisplayName: ferdy
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-20T02:33:45.683Z
Answers.Text: @ferdy All the games have it. Creation time is not start time. If you need a rated game with a forty minute disparity between creation and start, you can perform the same test I did: create the game (challenge a friend). Once it's accepted, wait 40 minutes to make the first moves. Or see the game Dargscisyhp used as an example. Game created at 1:25:40 remaining in tourney. 6s elapse between creation and game start. 22s elapse during play. But using the berserk API shows 27.5s between creation and final move.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-20T03:04:37.917Z
Answers.Text: Lichess has a system to limit the first move wait time to 24s. If first move is not sent the game is aborted.
Answers.UserDisplayName: ferdy
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-20T03:08:05.627Z
Answers.Text: Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/134286/discussion-between-l-scott-johnson-and-ferdy).
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-16T20:33:20.547Z
Answers.LastActivityDate: 2022-02-16T20:46:33.290Z
Answers.LastEditDate: 2022-02-16T20:46:33.290Z
Answers.UserDisplayName: ferdy
Answers.Body: <p>I tried to get some data from chess.com using their <a href="https://www.chess.com/news/view/published-data-api" rel="nofollow noreferrer">published api</a>. I use the <a href="https://www.chess.com/news/view/published-data-api#pubapi-endpoint-games-archive-list" rel="nofollow noreferrer">game archive</a> endpoint to get the data, and use the <a href="https://www.chess.com/news/view/published-data-api#pubapi-leaderboards" rel="nofollow noreferrer">leaderboard</a> endpoint to get the top 16 players in bullet.</p>
  <p>Typical game header in the pgn from pgn key of the returned request response.</p>
  <pre><code>[Event &quot;Live Chess&quot;]
  [Site &quot;Chess.com&quot;]
  [Date &quot;2020.09.07&quot;]
  [Round &quot;-&quot;]
  [White &quot;DexyDex&quot;]
  [Black &quot;Orange_Ghost&quot;]
  [Result &quot;1-0&quot;]
  [CurrentPosition &quot;1Q3B2/1R6/5p1k/3q1P1p/1P1N2pP/2P1r3/6PK/8 b - -&quot;]
  [Timezone &quot;UTC&quot;]
  [ECO &quot;C64&quot;]
  [ECOUrl &quot;https://www.chess.com/openings/Ruy-Lopez-Opening-Classical-Defense-4.O-O-d6&quot;]
  [UTCDate &quot;2020.09.07&quot;]
  [UTCTime &quot;21:54:44&quot;]
  [WhiteElo &quot;2839&quot;]
  [BlackElo &quot;2849&quot;]
  [TimeControl &quot;60&quot;]
  [Termination &quot;DexyDex won by checkmate&quot;]
  [StartTime &quot;21:54:44&quot;]
  [EndDate &quot;2020.09.07&quot;]
  [EndTime &quot;21:56:43&quot;]
  [Link &quot;https://www.chess.com/game/live/5413100443&quot;]
  </code></pre>
  <p>Elapse time can be calculated using the EndTime and StartTime tag values.</p>
  <h4>Top bullet players</h4>
  <pre><code>['Alexander_Zubov', 'AnishGiri', 'Chefshouse',
  'DanielNaroditsky', 'GMWSO', 'Hikaru', 'Indianlad',
  'nihalsarin', 'NikoTheodorou', 'Oleksandr_Bortnyk',
  'Orange_Ghost', 'RaunakSadhwani2005', 'SmurferHe',
  'spicycaterpillar', 'wonderfultime', 'Zhigalko_Sergei']
  </code></pre>
  <h4>Sample datasets</h4>
  <pre><code>   elapse_sec  tc                            termi                                         link
  0         142  60             chessawp won on time   https://www.chess.com/game/live/3359644035
  1         123  60             chessawp won on time   https://www.chess.com/game/live/3359654153
  2         105  60  TrimitziosP7 won by resignation  https://www.chess.com/game/live/38857280443
  3         157  60         TrimitziosP7 won on time  https://www.chess.com/game/live/38857733457
  4         111  60     denizozen won by resignation  https://www.chess.com/game/live/38866804411
         elapse_sec  tc                               termi                                        link
  19406         144  60         Zhigalko_Sergei won on time  https://www.chess.com/game/live/2793173203
  19407          52  60  Zhigalko_Sergei won by resignation  https://www.chess.com/game/live/2793177225
  19408         131  60    Zhigalko_Sergei won by checkmate  https://www.chess.com/game/live/2831119397
  19409         109  60          Kanallija won by checkmate  https://www.chess.com/game/live/2831121747
  19410         120  60        Kanallija won by resignation  https://www.chess.com/game/live/2831123668
  </code></pre>
  <h4>Figures</h4>
  <pre><code>datasets: 19411
  mean: 108
  stdev: 35
  </code></pre>
  <h4>Distribution plot</h4>
  <p><a href="https://i.sstatic.net/AnuCB.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/AnuCB.png" alt="enter image description here" /></a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-21T17:45:27.903Z
Answers.LastActivityDate: 2022-02-21T18:29:11.347Z
Answers.LastEditDate: 2022-02-21T18:29:11.347Z
Answers.UserDisplayName: ferdy
Answers.Body: <p>Per the suggestion by Rewan in the comments, I pulled the January 2022 log of games from lichess and looked at all the 1+0 games that finished with &quot;Normal&quot; or &quot;Time forfeit&quot; results with both players making at least one move each.</p>
  <p>The code I used is included below.</p>
  <p>Notes:</p>
  <ul>
  <li><p>Elapsed time is calculated as the sum of the starting clocks for each player minus the sum of the ending clocks for each player. Starting clocks (rather than a constant 120s) are used to handle the case when a player berserks.</p>
  </li>
  <li><p>I exclude cases where players gave their opponents more time (since this makes calculating elapsed time impossible from the PGN data given). At least, I try to; there are some cases that will be undetectable, such as giving time and the opponent using up all of that time prior to making their next more.</p>
  </li>
  <li><p>I do not use wall clock game creation time and game end time so as to avoid having the calculation artificially inflated with the extra non-game time introduced by the <a href="https://lichess.org/forum/lichess-feedback/query-how-is-time-spent-playing-on-profile-calculated#10" rel="nofollow noreferrer">delay between game creation and game start</a> and <a href="https://lichess.org/forum/general-chess-discussion/fast-blitzbullet-not-fair-due-to-time-adjustment-from-server" rel="nofollow noreferrer">lag/ping latency</a>.</p>
  </li>
  </ul>
  <p>Number of games:  27,398,824<br />
  Average time: 93.51 seconds<br />
  Median time: 104 seconds</p>
  <p>Using just the games in which neither player berserks:</p>
  <p>Number of games:  27,130,482<br />
  Average time: 93.77 seconds<br />
  Median time: 105 seconds</p>
  <p>Histogram of durations in that second set (no berserks):</p>
  <p><a href="https://i.sstatic.net/mI3X4.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/mI3X4.png" alt="Histogram of values with duration of games as the x-axis, showing a slow increase from 0 seconds to 80 seconds transitioning to a rapid growth from 80 seconds to 120 seconds" /></a></p>
  <p>Note the blip at t=60s. This duration is over-represented due to the games that have exactly two moves with white timing out. These stem, I believe, from challenges in which the challenged player does not immediately respond, and the challenger (playing white) doesn't notice when the challenge is ultimately accepted.</p>
  <p>Also note that the duration of the game is at least somewhat dependent on the strengths of the players. Here's a graph of the durations for games in which both players were about the same strength (Elo within 100 of each other) plotted against the players' average rating:</p>
  <p><a href="https://i.sstatic.net/TcpHL.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/TcpHL.png" alt="enter image description here" /></a></p>
  <p>I'm guessing the sudden dip at the end is an artifact stemming from the lower game count there, although perhaps to reach that level, premoves really become much more necessary.</p>
  <p>python3 code:</p>
  <pre><code>import glob
  import os
  import re
  import statistics
  
  def seconds(time_str):
      &quot;&quot;&quot;convert h:mm:ss to total seconds&quot;&quot;&quot;
      h, m, s = time_str.split(':')
      return int(h) * 3600 + int(m) * 60 + int(s)
  
  # function to verify each player's clock is monotone
  # decreasing (if a player is given time by their 
  # opponent, then the calculation of total game time
  # is not possible given only the PGN data supplied)
  def non_increasing(l):
      return all(x&gt;=y for x, y in zip(l, l[1:]))
  
  clock = re.compile(r'(?:\[%clk )(\d:\d\d:\d\d)')
  
  ignore = 0
  bullet = 0
  time = 0
  gameid = &quot;&quot;
  alltimes = []
  sanetimes = []
  
  statfile = open('stats.txt','w')
  statfile.write(&quot;%8s %3s %3s %5s %5s\n&quot;
    % (&quot;GameID&quot;, &quot;Dur&quot;, &quot;nPly&quot;, &quot;Wclk&quot;, &quot;Bclk&quot;))
  
  for filename in glob.glob('*.pgn'):
    print(filename)
    with open(os.path.join(os.getcwd(), filename), 'r') as f:
      line = f.readline()
  
      while(line):
  
        # &quot;Site&quot; is the second line of the each game, so it
        # is a good place to serve up the reset
        if(line.find('[Site ')&gt;=0):
          ignore = 0
          timeout = 0
          bullet = 0
          s = line.split('&quot;')
          s = s[1].split('/')
          gameid = s[-1]
  
        if(line.find('[Variant')&gt;=0):
          ignore = 1
  
        if(line.find('[TimeControl')&gt;=0):
          s = line.split('&quot;')
          if(s[1] == '60+0'):
            bullet = 1
  
        # ignore &quot;Abandoned&quot;, &quot;Unterminated&quot;, &quot;Rules infraction&quot;
        # and any other nonstandard endings.
        if(line.find('[Termination')&gt;=0):
          s = line.split('&quot;')
          if(s[1] == &quot;Time forfeit&quot;):
            timeout = 1
          elif(s[1] != &quot;Normal&quot;):
            ignore = 1
  
        if(line[0] == '1'):
          if((bullet == 1) and (ignore == 0)):
            times = clock.findall(line)
            if(len(times) &gt;= 2):
              secs = [ seconds(item) for item in times ]
              p1 = secs[::2]
              p2 = secs[1::2]
  
              # record the first clock value for each player.
              # it should be 60, but if the player berserked
              # then it will be 30. Whichever, we use this
              # value to determine the elapsed time for that
              # player's clock at the end.
              s1 = p1[0]
              s2 = p2[0]
  
              if(s1&lt;=60 and s2&lt;=60 and non_increasing(p1)
                  and non_increasing(p2)):
                t0 = secs[-1]
                if(timeout == 0):
                  t1 = secs[-2]
                  dur = s1+s2 - (t0 + t1)
                else:
                  dur = s1+s2 - t0
  
                if(dur &gt;= 0 and dur &lt;=120):
                  statfile.write(&quot;%8s %3d %3d %5d %5d\n&quot;
                    % (gameid, dur, len(secs), s1, s2))
  
                  alltimes.append(dur)
                  if(s1==60 and s2==60):
                    sanetimes.append(dur)
          
        line = f.readline()
  
  f.close()
  statfile.close()
  
  print(&quot;Number of games: &quot;, len(alltimes))
  print(&quot;Average time: %s seconds&quot;
    % ( statistics.mean(alltimes)))
  print(&quot;Median time: %s seconds&quot;
    % ( statistics.median(alltimes)))
  
  print(&quot;Number of non-berserked games: &quot;, len(sanetimes))
  print(&quot;Average time: %s seconds&quot;
    % ( statistics.mean(sanetimes)))
  print(&quot;Median time: %s seconds&quot;
    % ( statistics.median(sanetimes)))
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-10T20:25:05.587Z
Answers.Text: This is great. Just wanted to check if it includes resignations?
Answers.UserDisplayName: stevec
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-10T20:38:51.487Z
Answers.Text: Yes: mates, stalemates, draws, resignations, and loss on time are all counted. I can rerun it with a different filter if you like.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-10T20:41:57.577Z
Answers.Text: that’s perfect just wanted to confirm.
Answers.UserDisplayName: stevec
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-11T13:38:40.510Z
Answers.Text: No sorting: I just look for time control of 60+0 (it's given in seconds) and exclude certain cases like Rules Violations then look at the last two %clk values.  I note that if anyone "gives time", then this clk value will throw off the calculations (e.g., in some cases, a player ends with more than 60 seconds left on their clock, which the calculation will see as the game taking negative time: https://lichess.org/HySUH6IK ). I'll see about adding code to check that the clocks are at least non-increasing.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-11T14:07:59.500Z
Answers.Text: Adding for completeness: someone mentioned in another forum "*A berzeked game still has [TimeControl "60+0"] , so they are probably included ...You would need to look at the move time in the PGN's to tell if a player zerked. (Now, I don't think this would really change the numbers that much. At most a few seconds? Guessing here thru, but from all rated games, not that many are zerked)*"
Answers.UserDisplayName: stevec
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-11T15:16:23.157Z
Answers.Text: @stevec. Good point. Just the first clock for each player should tell you if a player berserks. The question is then whether to count that game in the stats or not. I'll run it both ways.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-13T17:02:29.760Z
Answers.Text: Hi @L.ScottJohnson I wonder if you might post the code you used to analyze this somewhere? I got slightly different results and was also wondering how you were able to go through such a massive file so quickly. I left my computer running overnight trying to analyze the games, but it had not finished by morning.
  
  Also, I could not figure out an efficient way to handle situations where someone has given his opponent extra time.
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-14T13:09:26.370Z
Answers.Text: Sure. I'm re-running the code now to handle one more type of outlier: the monotonic case where "add time" was used prior to the first move. e.g.: https://lichess.org/VDLllWBA . I'll post "sane" stats (assuming no other outliers are revealed) and the code when that run is done (takes about 2.5 hours).
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-15T19:38:59.440Z
Answers.Text: @L.ScottJohnson I'm impressed that your computer is able to process the entire database of games in 2.5 hours. I was able to extract out the first million bullet games, but that alone took a few hours. I also find the huge number of games that go to the wire interesting. I wonder why I did not find the same. The histograms created from my data can be found at this [Math stackexchange question](https://math.stackexchange.com/questions/4381681/what-sort-of-distribution-should-you-expect-for-the-total-time-taken-in-bullet-c)
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-15T19:44:30.967Z
Answers.Text: A couple of differences in our methodologies: I did not exclude "nonstandard" endings, which if I go through a second pass I will. I limited to games with an event title of "Rated Bullet game" so I did not have to exclude berserkers. I did not check to see if every time was nonincreasing, so I will have included some instances where time was given when I should not have. Overall the statistics were close -- mean total time was 92.3 and median was 104. However, none of this explains why you have a blip at t=120 and I don't (at least not that I can see)
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-15T20:02:09.627Z
Answers.Text: If you limited to "Rated Bullet game", that itself may be why you saw no (noticeable) blip at 60s (meaning unrated games are more prone to such, IMO). If you're interested, my hardware is a 2017 iMac, 3.8 GHz Quad-Core Intel Core i5, 64GB RAM, reading from a PCI SSD.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-15T20:09:49.053Z
Answers.Text: @Dargscisyhp For the games that time out, are you taking the timed-out player's final clock to be zero or are you using their last %clk value?
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-15T20:13:15.340Z
Answers.Text: @L.ScottJohnson I'm using their last %clk value. Perhaps there's the discrepancy? I don't think the database includes unrated games but I may be mistkaen.
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-15T20:30:02.057Z
Answers.Text: @Dargscisyhp That may explain why you're not getting blips at 60s and 120s. When the ending condition is timeout, the timed-out player's final clock is 0 but this is not accurately reflected in the PGN's move list. A 2-ply game that takes 60s you will see as taking only 0s.
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-15T21:17:07.487Z
Answers.Text: @L.ScottJohnson You're right, that was it. I can recreate the blips. 93.7 mean, 105 median (over 100,000 games).
Answers.UserDisplayName: Dargscisyhp
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-17T02:20:44.237Z
Answers.Text: Why the spike at 120s? Do so many games really come down to less than a second?  I guess it might be from the ability to premove and use no time.
Answers.UserDisplayName: Edward
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-17T11:32:09.420Z
Answers.Text: @Edward yes. When you and your opponent are low on time, you tend to enter a time scramble where you both just push your pieces furiously around in the hope that your opponent flags
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-03-05T15:18:13.123Z
Answers.Text: @L.ScottJohnson Yes, I know this.  I was a bit surprised at the large difference between flags at <1s vs flags at 1-2s
Answers.UserDisplayName: Edward
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-02-10T20:01:38.380Z
Answers.LastActivityDate: 2022-03-20T12:11:08.187Z
Answers.LastEditDate: 2022-03-20T12:11:08.187Z
Answers.UserDisplayName: L. Scott Johnson
Body: <p>Bullet chess gives each player 1 minute to make all their moves - if that minute passes and they haven't checkmated their opponent, they lose (or if insufficient material, a draw).</p>
  <p>Since chess has 2 players, the longest a bullet chess game can go for is approximately 2 minutes (or slightly under because it's not possible for both clocks to count down to exactly zero at the same time).</p>
  <p>But many bullet games are much shorter than 2 minutes, for example in games where a checkmate or resignation happens very early in the game (some last only a few seconds).</p>
  <p>So what is the <em>average</em> duration of a game of bullet chess?</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-02-08T04:31:59.430Z
Comments.Text: I think combing the average of the last 10000 or so bullet games on lichess would give a pretty good estimate.
Comments.UserDisplayName: Rewan Demontay
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-02-08T12:18:43.783Z
Comments.Text: @RewanDemontay thanks for the great suggestion. I checked out the lichess API and couldn't find an easy way to get the last 10k bullet games. Sure enough, I joined the lichess discord (api-bots-boards channel) and asked, and within 5 seconds flat Thibault himself replied, who said it's not possible via API, but you can download the entire month's database). Unfortunately it's about 30GB - too big for me to download right now, but if anyone's got the bandwidth, here's the link. Perhaps they could grab the last 10k bullet games and pastebin them for us all to use. https://database.lichess.org/
Comments.UserDisplayName: stevec
Tags: <statistics><bullet-chess>
Title: What's the average total time for a game of bullet chess?
ThreadText: # What's the average total time for a game of bullet chess?
  
  (Asked by: username_0 on 2022-02-08)
  
  Bullet chess gives each player 1 minute to make all their moves - if that minute passes and they haven't checkmated their opponent, they lose (or if insufficient material, a draw).
  
  Since chess has 2 players, the longest a bullet chess game can go for is approximately 2 minutes (or slightly under because it's not possible for both clocks to count down to exactly zero at the same time).
  
  But many bullet games are much shorter than 2 minutes, for example in games where a checkmate or resignation happens very early in the game (some last only a few seconds).
  
  So what is the *average* duration of a game of bullet chess?
  
  **Tags:** statistics, bullet-chess
  
  > **Comments:**
  > **username_1**: I think combing the average of the last 10000 or so bullet games on lichess would give a pretty good estimate.  
  > **username_0**: @RewanDemontay thanks for the great suggestion. I checked out the lichess API and couldn't find an easy way to get the last 10k bullet games. Sure enough, I joined the lichess discord (api-bots-boards channel) and asked, and within 5 seconds flat Thibault himself replied, who said it's not possible via API, but you can download the entire month's database). Unfortunately it's about 30GB - too big for me to download right now, but if anyone's got the bandwidth, here's the link. Perhaps they could grab the last 10k bullet games and pastebin them for us all to use. https://database.lichess.org/  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_3 on 2022-02-10. Score: 13 | Accepted answer
  
  Per the suggestion by Rewan in the comments, I pulled the January 2022 log of games from lichess and looked at all the 1+0 games that finished with "Normal" or "Time forfeit" results with both players making at least one move each.
  The code I used is included below.
  Notes:
  
  Elapsed time is calculated as the sum of the starting clocks for each player minus the sum of the ending clocks for each player. Starting clocks (rather than a constant 120s) are used to handle the case when a player berserks.
  
  I exclude cases where players gave their opponents more time (since this makes calculating elapsed time impossible from the PGN data given). At least, I try to; there are some cases that will be undetectable, such as giving time and the opponent using up all of that time prior to making their next more.
  
  I do not use wall clock game creation time and game end time so as to avoid having the calculation artificially inflated with the extra non-game time introduced by the delay between game creation and game start and lag/ping latency.
  
  
  Number of games:  27,398,824
  Average time: 93.51 seconds
  Median time: 104 seconds
  Using just the games in which neither player berserks:
  Number of games:  27,130,482
  Average time: 93.77 seconds
  Median time: 105 seconds
  Histogram of durations in that second set (no berserks):
  
  Note the blip at t=60s. This duration is over-represented due to the games that have exactly two moves with white timing out. These stem, I believe, from challenges in which the challenged player does not immediately respond, and the challenger (playing white) doesn't notice when the challenge is ultimately accepted.
  Also note that the duration of the game is at least somewhat dependent on the strengths of the players. Here's a graph of the durations for games in which both players were about the same strength (Elo within 100 of each other) plotted against the players' average rating:
  
  I'm guessing the sudden dip at the end is an artifact stemming from the lower game count there, although perhaps to reach that level, premoves really become much more necessary.
  python3 code:
  import glob
  import os
  import re
  import statistics
  
  def seconds(time_str):
      """convert h:mm:ss to total seconds"""
      h, m, s = time_str.split(':')
      return int(h) * 3600 + int(m) * 60 + int(s)
  
  # function to verify each player's clock is monotone
  # decreasing (if a player is given time by their 
  # opponent, then the calculation of total game time
  # is not possible given only the PGN data supplied)
  def non_increasing(l):
      return all(x>=y for x, y in zip(l, l[1:]))
  
  clock = re.compile(r'(?:\[%clk )(\d:\d\d:\d\d)')
  
  ignore = 0
  bullet = 0
  time = 0
  gameid = ""
  alltimes = []
  sanetimes = []
  
  statfile = open('stats.txt','w')
  statfile.write("%8s %3s %3s %5s %5s\n"
    % ("GameID", "Dur", "nPly", "Wclk", "Bclk"))
  
  for filename in glob.glob('*.pgn'):
    print(filename)
    with open(os.path.join(os.getcwd(), filename), 'r') as f:
      line = f.readline()
  
      while(line):
  
        # "Site" is the second line of the each game, so it
        # is a good place to serve up the reset
        if(line.find('[Site ')>=0):
          ignore = 0
          timeout = 0
          bullet = 0
          s = line.split('"')
          s = s[1].split('/')
          gameid = s[-1]
  
        if(line.find('[Variant')>=0):
          ignore = 1
  
        if(line.find('[TimeControl')>=0):
          s = line.split('"')
          if(s[1] == '60+0'):
            bullet = 1
  
        # ignore "Abandoned", "Unterminated", "Rules infraction"
        # and any other nonstandard endings.
        if(line.find('[Termination')>=0):
          s = line.split('"')
          if(s[1] == "Time forfeit"):
            timeout = 1
          elif(s[1] != "Normal"):
            ignore = 1
  
        if(line[0] == '1'):
          if((bullet == 1) and (ignore == 0)):
            times = clock.findall(line)
            if(len(times) >= 2):
              secs = [ seconds(item) for item in times ]
              p1 = secs[::2]
              p2 = secs[1::2]
  
              # record the first clock value for each player.
              # it should be 60, but if the player berserked
              # then it will be 30. Whichever, we use this
              # value to determine the elapsed time for that
              # player's clock at the end.
              s1 = p1[0]
              s2 = p2[0]
  
              if(s1<=60 and s2<=60 and non_increasing(p1)
                  and non_increasing(p2)):
                t0 = secs[-1]
                if(timeout == 0):
                  t1 = secs[-2]
                  dur = s1+s2 - (t0 + t1)
                else:
                  dur = s1+s2 - t0
  
                if(dur >= 0 and dur <=120):
                  statfile.write("%8s %3d %3d %5d %5d\n"
                    % (gameid, dur, len(secs), s1, s2))
  
                  alltimes.append(dur)
                  if(s1==60 and s2==60):
                    sanetimes.append(dur)
          
        line = f.readline()
  
  f.close()
  statfile.close()
  
  print("Number of games: ", len(alltimes))
  print("Average time: %s seconds"
    % ( statistics.mean(alltimes)))
  print("Median time: %s seconds"
    % ( statistics.median(alltimes)))
  
  print("Number of non-berserked games: ", len(sanetimes))
  print("Average time: %s seconds"
    % ( statistics.mean(sanetimes)))
  print("Median time: %s seconds"
    % ( statistics.median(sanetimes)))
  
  > **Comments:**
  > **username_0**: This is great. Just wanted to check if it includes resignations?  
  > **username_3**: Yes: mates, stalemates, draws, resignations, and loss on time are all counted. I can rerun it with a different filter if you like.  
  > **username_0**: that’s perfect just wanted to confirm.  
  > **username_3**: No sorting: I just look for time control of 60+0 (it's given in seconds) and exclude certain cases like Rules Violations then look at the last two %clk values.  I note that if anyone "gives time", then this clk value will throw off the calculations (e.g., in some cases, a player ends with more than 60 seconds left on their clock, which the calculation will see as the game taking negative time: https://lichess.org/HySUH6IK ). I'll see about adding code to check that the clocks are at least non-increasing.  
  > **username_0**: Adding for completeness: someone mentioned in another forum "*A berzeked game still has [TimeControl "60+0"] , so they are probably included ...You would need to look at the move time in the PGN's to tell if a player zerked. (Now, I don't think this would really change the numbers that much. At most a few seconds? Guessing here thru, but from all rated games, not that many are zerked)*"  
  > **username_3**: @username_0. Good point. Just the first clock for each player should tell you if a player berserks. The question is then whether to count that game in the stats or not. I'll run it both ways.  
  > **username_4**: Hi @L.ScottJohnson I wonder if you might post the code you used to analyze this somewhere? I got slightly different results and was also wondering how you were able to go through such a massive file so quickly. I left my computer running overnight trying to analyze the games, but it had not finished by morning.  Also, I could not figure out an efficient way to handle situations where someone has given his opponent extra time.  
  > **username_3**: Sure. I'm re-running the code now to handle one more type of outlier: the monotonic case where "add time" was used prior to the first move. e.g.: https://lichess.org/VDLllWBA . I'll post "sane" stats (assuming no other outliers are revealed) and the code when that run is done (takes about 2.5 hours).  
  > **username_4**: @L.ScottJohnson I'm impressed that your computer is able to process the entire database of games in 2.5 hours. I was able to extract out the first million bullet games, but that alone took a few hours. I also find the huge number of games that go to the wire interesting. I wonder why I did not find the same. The histograms created from my data can be found at this [Math stackexchange question](https://math.stackexchange.com/questions/4381681/what-sort-of-distribution-should-you-expect-for-the-total-time-taken-in-bullet-c)  
  > **username_4**: A couple of differences in our methodologies: I did not exclude "nonstandard" endings, which if I go through a second pass I will. I limited to games with an event title of "Rated Bullet game" so I did not have to exclude berserkers. I did not check to see if every time was nonincreasing, so I will have included some instances where time was given when I should not have. Overall the statistics were close -- mean total time was 92.3 and median was 104. However, none of this explains why you have a blip at t=120 and I don't (at least not that I can see)  
  > **username_3**: If you limited to "Rated Bullet game", that itself may be why you saw no (noticeable) blip at 60s (meaning unrated games are more prone to such, IMO). If you're interested, my hardware is a 2017 iMac, 3.8 GHz Quad-Core Intel Core i5, 64GB RAM, reading from a PCI SSD.  
  > **username_3**: @username_4 For the games that time out, are you taking the timed-out player's final clock to be zero or are you using their last %clk value?  
  > **username_4**: @L.ScottJohnson I'm using their last %clk value. Perhaps there's the discrepancy? I don't think the database includes unrated games but I may be mistkaen.  
  > **username_3**: @username_4 That may explain why you're not getting blips at 60s and 120s. When the ending condition is timeout, the timed-out player's final clock is 0 but this is not accurately reflected in the PGN's move list. A 2-ply game that takes 60s you will see as taking only 0s.  
  > **username_4**: @L.ScottJohnson You're right, that was it. I can recreate the blips. 93.7 mean, 105 median (over 100,000 games).  
  > **username_5**: Why the spike at 120s? Do so many games really come down to less than a second?  I guess it might be from the ability to premove and use no time.  
  > **username_3**: @username_5 yes. When you and your opponent are low on time, you tend to enter a time scramble where you both just push your pieces furiously around in the hope that your opponent flags  
  > **username_5**: @L.ScottJohnson Yes, I know this.  I was a bit surprised at the large difference between flags at <1s vs flags at 1-2s  
  
  ---
  
  ### Answer by username_2 on 2022-02-16. Score: 4
  
  Collected data from the top 100 bullet players in Lichess using the berserk module from lichess api.
  The function client.games.export_by_player() can give info about the games played by a player. This includes createdAt and lastMoveAt timestamps values from which we can calculate the duration of the game.
  Be noted that extracting game time duration through game clk info may not be appropriate because most of these players are pre-moving. Even if their clock is at 1s some players can still make some moves with their clock still at 1s.
  I. Bullet games at TC 60+0
  Some figures
  Bullet games from top 100 bullet Lichess players, each player has
  around 200 games at tc 60+0 less duplicates.
  num data: 18125
  min   (s): 21
  max   (s): 200
  mean  (s): 103
  stdev (s): 32
  
  Overall distribution
  There are games that are more than 120s due to pre-moves.
  
  Resigned games
  It peaks close to 100s.
  
  Checkmates
  
  Time forfeit
  
  Draws
  
  Stalemate
  
  Overall result by game termination
  
  II. Bullet games at TC 30+0
  Bullet games from top 100 bullet Lichess players at TC 30+0
  num data: 6963
  min   (s): 21
  max   (s): 120
  mean  (s): 63
  stdev (s): 17
  
  > **Comments:**
  > **username_3**: How do premoves generate more time on the clock?  
  > **username_4**: I wonder if that has to do with the way the server accounts for latency. I've wondered the same thing while playing on lichess -- games that are both down to where each player has 1 to 2 seconds left seem to go a lot longer than the 2-4 seconds indicated by the clock.  
  > **username_4**: @L.ScottJohnson [Here's an example](https://www.youtube.com/watch?v=G2AMN9tHSB0&t=2324s) where I believe that happens. This is an 8s/0 game on both sides, and starts at the 38:44 mark. At the end of the game the players have a combined 3.9 seconds left, which is at the 39:07 mark. That means 12.1 seconds of in game time elapsed, but 23 seconds of real time!  
  > **username_3**: @username_4 Sure. But the question is formulated around clock time, not real time.  
  > **username_4**: @L.ScottJohnson Probably the question is formulated under the assumption that clock time and real time are one and the same. Either way, both answers are interesting.  
  > **username_3**: Another factor, perhaps a bigger factor, in the discrepancy is that createdAt is not the time the game started. The added time from those gaps (between game creation and game start) likely dwarfs the accumulated from pre-moves latency. As an extreme example, the 1+0 game I tested with, which ended after 3 seconds, shows 40 minutes and 20 seconds elapsed from creation to last move.  
  > **username_2**: 1+0, 40m+20s, that is weird, could you post the game id?  
  > **username_3**: It's extreme length for a gap, but the gap existing is common. It's the difference between the time the game is created and the time the game begins. Reference test game: https://lichess.org/dotb5hRF  
  > **username_2**: That game is casual. Can you find a rated game having a weird elapse time? In my datasets I use rated games.  
  > **username_3**: @username_2 All the games have it. Creation time is not start time. If you need a rated game with a forty minute disparity between creation and start, you can perform the same test I did: create the game (challenge a friend). Once it's accepted, wait 40 minutes to make the first moves. Or see the game username_4 used as an example. Game created at 1:25:40 remaining in tourney. 6s elapse between creation and game start. 22s elapse during play. But using the berserk API shows 27.5s between creation and final move.  
  > **username_2**: Lichess has a system to limit the first move wait time to 24s. If first move is not sent the game is aborted.  
  > **username_3**: Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/134286/discussion-between-l-scott-johnson-and-username_2).  
  
  ---
  
  ### Answer by username_2 on 2022-02-21. Score: 1
  
  I tried to get some data from chess.com using their published api. I use the game archive endpoint to get the data, and use the leaderboard endpoint to get the top 16 players in bullet.
  Typical game header in the pgn from pgn key of the returned request response.
  [Event "Live Chess"]
  [Site "Chess.com"]
  [Date "2020.09.07"]
  [Round "-"]
  [White "DexyDex"]
  [Black "Orange_Ghost"]
  [Result "1-0"]
  [CurrentPosition "1Q3B2/1R6/5p1k/3q1P1p/1P1N2pP/2P1r3/6PK/8 b - -"]
  [Timezone "UTC"]
  [ECO "C64"]
  [ECOUrl "https://www.chess.com/openings/Ruy-Lopez-Opening-Classical-Defense-4.O-O-d6"]
  [UTCDate "2020.09.07"]
  [UTCTime "21:54:44"]
  [WhiteElo "2839"]
  [BlackElo "2849"]
  [TimeControl "60"]
  [Termination "DexyDex won by checkmate"]
  [StartTime "21:54:44"]
  [EndDate "2020.09.07"]
  [EndTime "21:56:43"]
  [Link "https://www.chess.com/game/live/5413100443"]
  
  Elapse time can be calculated using the EndTime and StartTime tag values.
  Top bullet players
  ['Alexander_Zubov', 'AnishGiri', 'Chefshouse',
  'DanielNaroditsky', 'GMWSO', 'Hikaru', 'Indianlad',
  'nihalsarin', 'NikoTheodorou', 'Oleksandr_Bortnyk',
  'Orange_Ghost', 'RaunakSadhwani2005', 'SmurferHe',
  'spicycaterpillar', 'wonderfultime', 'Zhigalko_Sergei']
  
  Sample datasets
     elapse_sec  tc                            termi                                         link
  0         142  60             chessawp won on time   https://www.chess.com/game/live/3359644035
  1         123  60             chessawp won on time   https://www.chess.com/game/live/3359654153
  2         105  60  TrimitziosP7 won by resignation  https://www.chess.com/game/live/38857280443
  3         157  60         TrimitziosP7 won on time  https://www.chess.com/game/live/38857733457
  4         111  60     denizozen won by resignation  https://www.chess.com/game/live/38866804411
         elapse_sec  tc                               termi                                        link
  19406         144  60         Zhigalko_Sergei won on time  https://www.chess.com/game/live/2793173203
  19407          52  60  Zhigalko_Sergei won by resignation  https://www.chess.com/game/live/2793177225
  19408         131  60    Zhigalko_Sergei won by checkmate  https://www.chess.com/game/live/2831119397
  19409         109  60          Kanallija won by checkmate  https://www.chess.com/game/live/2831121747
  19410         120  60        Kanallija won by resignation  https://www.chess.com/game/live/2831123668
  
  Figures
  datasets: 19411
  mean: 108
  stdev: 35
  
  Distribution plot
  
  
  ---
  
  