{"_id":"546b9fb462515a14007ebc7d","user":"5467aefc016b480800bc7c46","project":"5435c6595e1b20200043836f","version":{"_id":"5467ae1798b68408002689a6","project":"5435c6595e1b20200043836f","__v":1,"forked_from":"5435c6595e1b202000438372","createdAt":"2014-11-15T19:48:39.092Z","releaseDate":"2014-11-15T19:48:39.092Z","categories":["5467ae1798b68408002689a7","5467ae1798b68408002689a8"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"4.2.0","version":"4.2"},"__v":11,"category":{"_id":"5467ae1798b68408002689a8","pages":["5467ae1898b68408002689a9","5467ae1898b68408002689aa","546b9fb462515a14007ebc7d"],"version":"5467ae1798b68408002689a6","__v":2,"project":"5435c6595e1b20200043836f","sync":{"url":"","isSync":false},"reference":true,"createdAt":"2014-11-15T19:32:50.301Z","from_sync":false,"order":0,"slug":"api","title":"API"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2014-11-18T19:36:20.062Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"try":true,"basic_auth":false,"auth":"never","params":[],"url":""},"isReference":false,"order":2,"body":"There are six time control systems on OGS, a start clock system, multiple ways to pause games, and latency compensation considerations when dealing with real-time games. While all of this may seem daunting at first, once you wrap your head around it it's not so bad - this document will help guide you through that process.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Applicable fields within the game object.\"\n}\n[/block]\nThere are three fields of interest within a game data object. `time_control`, `clock`, and `pause_control` (which won't exist unless the game has been paused at least once).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"time_control\"\n}\n[/block]\nThe `time_control` field is used to describe the time control system being used in the game and does not change. This field takes on one of six structures, depending on what time control system is used\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"time_control\\\"  : \\\"fischer\\\",\\n  \\\"initial_time\\\"  : 86400, /* in seconds */\\n  \\\"time_increment\\\": 3600,  /* in seconds */\\n  \\\"max_time\\\"      : 86400  /* in seconds */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Fischer\"\n    },\n    {\n      \"code\": \"{\\n  \\\"time_control\\\": \\\"byoyomi\\\",\\n  \\\"main_time\\\"   : 86400, /* seconds */\\n  \\\"period_time\\\" : 3600,  /* seconds */\\n  \\\"periods\\\"     : 5      /* count */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Byo-Yomi\"\n    },\n    {\n      \"code\": \"{\\n  \\\"time_control\\\": \\\"simple\\\",\\n  \\\"per_move\\\"    : 86400  /* seconds */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Simple\"\n    },\n    {\n      \"code\": \"{\\n  \\\"time_control\\\"     : \\\"canadian\\\",\\n  \\\"main_time\\\"        : 86400, /* seconds */\\n  \\\"period_time\\\"      : 86400, /* seconds */\\n  \\\"stones_per_period\\\": 10     /* count */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Canadian\"\n    },\n    {\n      \"code\": \"{\\n  \\\"time_control\\\": \\\"absolute\\\",\\n  \\\"total_time\\\"  : 86400  /* seconds */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Absolute\"\n    },\n    {\n      \"code\": \"{\\n  \\\"time_control\\\": \\\"none\\\"\\n}\",\n      \"language\": \"json\",\n      \"name\": \"None\"\n    }\n  ]\n}\n[/block]\n**Fischer**: Clock begins with the `initial_time`, after each move `time_increment` is added up to a maximum of `max_time`. Displays only need to show the current amount of time remaining, and optionally how much time will be added after each move.\n\n**Byo-Yomi**: Clock begins with `main_time`, after the main time is exhausted the clock is set to `period_time` and the number of periods is decreased. If the player makes a move before the period is up, the clock is reset to `period_time`. If the player exhausts the clock again and there are periods remaining, the clock is set to the `period_time` again and the period counter is decreased. This continues until all periods have been used up, at which time a player loses on time.\n\nDIsplays should show the base time, and the number of periods left, and optionally how long each period is.\n\n**Simple**: Clocks begin with `per_move` time. After each move the clock is reset to `per_move`.\n\n**Canadian**: Clocks being with `main_time` and use this time until it is exhausted, at which point the clock is set to `period_time`. Once in overtime, after each move the `stones_per_period` counter is decreased until it reaches zero. Once this happens the clock is reset to `period_time` and the `stones_per_period` counter is reset. Displays should show the time remaining, and if the user is in overtime then the `stones_per_move` counter should also be shown.\n\n**Absolute**: The clock is set to `total_time` and only decreases.\n\n**None**: The simplest time control system, no clock is used or displayed.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"clock\"\n}\n[/block]\nThe `clock` field contains the current state of the game clock and changes once per move.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\n    black_time: {\\n        period_time: 30, /* seconds */\\n        periods: 5,\\n        thinking_time: 1200 /* seconds */\\n    },\\n    white_time: {\\n        period_time: 30, /* seconds */\\n        periods: 5,\\n        thinking_time: 360.90599999999995   /* seconds */\\n    },\\n    current_player: 12751,\\n    last_move: 1416172879750, /* milliseconds since epoch */\\n    now: 1416093910807,       /* milliseconds since epoch */\\n    \\n    start_mode: false, /* removed after a game begins */\\n    \\n  \\t/* These fields are used by the server, but are not\\n     * necessary for clients to display clock information */\\n    game_id: 989449,\\n    black_player_id: 12751,\\n    white_player_id: 1,  \\n    title: \\\"friendly match\\\",\\n    paused_since: 1416093910,   /* seconds since epoch */\\n    expiration_delta: 1350000,  /* milliseconds */\\n    expiration: 1416174229750,  /* milliseconds since epoch */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Clock\"\n    }\n  ]\n}\n[/block]\nThe `black_time` and `white_time` fields take on different forms depending on what time control system is being used\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n\\tthinking_time: 12345, /* seconds */\\n  \\n  /* Used by the server, unnecessary for the client */\\n  skip_bonus: false\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Fischer\"\n    },\n    {\n      \"code\": \"{\\n  thinking_time: 12345, /* seconds */\\n  periods      : 3,     /* periods left */\\n  period_time  : 30,    /* seconds */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Byo-Yomi\"\n    },\n    {\n      \"code\": \"123455  /* this field is simply a number of seconds on the clock, will be 0 for the player not playing (this is subject to change, and may become number of seconds left on the clock for the last move instead of simply 0 in the future.) */\",\n      \"language\": \"json\",\n      \"name\": \"Simple\"\n    },\n    {\n      \"code\": \"{\\n  thinking_time : 12345, /* seconds */\\n  \\n  /* applicable only when thinking_time == 0, however \\n   * the fields will always exist */\\n  moves_left    : 20,    /* moves left in this period  */\\n  block_time    : 3600   /* seconds left in this period  */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Canadian\"\n    },\n    {\n      \"code\": \"{\\n  thinking_time: 12345  /* seconds */\\n}\",\n      \"language\": \"json\",\n      \"name\": \"Absolute\"\n    },\n    {\n      \"code\": \"# The `black_time` and `white_time` fields do not exist for the `none` time control.\",\n      \"language\": \"text\",\n      \"name\": \"None\"\n    }\n  ]\n}\n[/block]\nWhich is an ugly mess, and we apologize. If we had to do it over again, it'd be a lot different and notably cleaner (or at least that's what we'd like to think.)\n\nDetails on how to make use of these fields to turn the `clock` into something you can show to your users will follow after the section on `pause_control`\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"pause_control\"\n}\n[/block]\nGames can be paused for several reasons, such as a player having clicked the pause button, the game has been paused for a system event, the game has been paused on the weekend (a correspondence game feature), users are on vacation, or because the game is in the stone removal phase.\n\nIf the game is paused the game object will contain the `pause_control` field as an object and will contain one or more entries describing what is currently pausing the game. *Note: if a game has been paused and unpaused, the `pause_control` field may still be present in the game data object, but it will contain no fields.*\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"paused\\\": {\\n    \\\"pauses_left\\\": 4,\\n    \\\"pausing_player_id\\\": 1\\n  },\\n  \\\"weekend\\\": true,\\n  \\\"system\\\": true,\\n  \\\"vacation-{{player id}}\\\": true,\\n  \\\"stone-removal\\\": true\\n}\",\n      \"language\": \"json\",\n      \"name\": \"pause_control\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Putting it all together\"\n}\n[/block]\nUltimately the goal of understanding the OGS time control system is so you can display a clock showing how much time is left before either a timeout or the start of your next byo-yomi / canadian period. Additionally you have to handle the start clock (which just tells the user how much time is left before the first move must be made), and when to display whether the game is paused or not. The following pseudo-code should help illustrate how to do this - at the end you'll be left with `left` which is intended to be the number of milliseconds left before a timeout / period rollover.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"if clock.start_mode:\\n\\tDisplay time until clock.expiration\\nelif `pause_control` exists and is non-empty:\\n  Display \\\"Paused\\\"\\nelse:\\n  let player_time be black_time or white_time appropriately\\n  let now_delta = NOW() - clock.now\\n  let base_time = clock.last_move + now_delta\\n  if player_time is number:\\n  \\t# simple time\\n    let time_left = player_time - NOW()\\n  if player_time is object:\\n    let left = base_time + player_time.thinking_time*1000 - now\\n    if moves_left is a field in player_time: # canadian\\n    \\tif left < 0 or player_time.thinking_time == 0:\\n      \\tleft = base_time + (player_time.thinking_time + \\\\\\n               player_time.block_time) * 1000 - now\\n    if periods is a field in player_time: # byo yomi\\n      if left < 0 or player_time.thinking_time == 0:\\n        let period_offset = floor((-left / 1000) / player_time.period_time)\\n        period_offset = max(0, period_offset)\\n        \\n        while left < 0:\\n        \\tleft += player_time.period_time * 1000\\n        \\n        \\n        let periods_left = (player_time.periods - period_offset) - 1\\n        if (player_time.periods - period_offset) - 1 < 0:\\n        \\tleft = 0\\n        \\n\\n# left now contains the number of milliseconds left \\n# on the clock before either a timeout or the start \\n# of the next byo-yomi or canadian period\",\n      \"language\": \"text\",\n      \"name\": \"Get time left on clock\"\n    },\n    {\n      \"code\": \"# The number of milliseconds since Jan. 1, 1970 (Epoch)\",\n      \"language\": \"text\",\n      \"name\": \"NOW()\"\n    }\n  ]\n}\n[/block]","excerpt":"","slug":"time-control","type":"basic","title":"Time control"}
There are six time control systems on OGS, a start clock system, multiple ways to pause games, and latency compensation considerations when dealing with real-time games. While all of this may seem daunting at first, once you wrap your head around it it's not so bad - this document will help guide you through that process. [block:api-header] { "type": "basic", "title": "Applicable fields within the game object." } [/block] There are three fields of interest within a game data object. `time_control`, `clock`, and `pause_control` (which won't exist unless the game has been paused at least once). [block:api-header] { "type": "basic", "title": "time_control" } [/block] The `time_control` field is used to describe the time control system being used in the game and does not change. This field takes on one of six structures, depending on what time control system is used [block:code] { "codes": [ { "code": "{\n \"time_control\" : \"fischer\",\n \"initial_time\" : 86400, /* in seconds */\n \"time_increment\": 3600, /* in seconds */\n \"max_time\" : 86400 /* in seconds */\n}", "language": "json", "name": "Fischer" }, { "code": "{\n \"time_control\": \"byoyomi\",\n \"main_time\" : 86400, /* seconds */\n \"period_time\" : 3600, /* seconds */\n \"periods\" : 5 /* count */\n}", "language": "json", "name": "Byo-Yomi" }, { "code": "{\n \"time_control\": \"simple\",\n \"per_move\" : 86400 /* seconds */\n}", "language": "json", "name": "Simple" }, { "code": "{\n \"time_control\" : \"canadian\",\n \"main_time\" : 86400, /* seconds */\n \"period_time\" : 86400, /* seconds */\n \"stones_per_period\": 10 /* count */\n}", "language": "json", "name": "Canadian" }, { "code": "{\n \"time_control\": \"absolute\",\n \"total_time\" : 86400 /* seconds */\n}", "language": "json", "name": "Absolute" }, { "code": "{\n \"time_control\": \"none\"\n}", "language": "json", "name": "None" } ] } [/block] **Fischer**: Clock begins with the `initial_time`, after each move `time_increment` is added up to a maximum of `max_time`. Displays only need to show the current amount of time remaining, and optionally how much time will be added after each move. **Byo-Yomi**: Clock begins with `main_time`, after the main time is exhausted the clock is set to `period_time` and the number of periods is decreased. If the player makes a move before the period is up, the clock is reset to `period_time`. If the player exhausts the clock again and there are periods remaining, the clock is set to the `period_time` again and the period counter is decreased. This continues until all periods have been used up, at which time a player loses on time. DIsplays should show the base time, and the number of periods left, and optionally how long each period is. **Simple**: Clocks begin with `per_move` time. After each move the clock is reset to `per_move`. **Canadian**: Clocks being with `main_time` and use this time until it is exhausted, at which point the clock is set to `period_time`. Once in overtime, after each move the `stones_per_period` counter is decreased until it reaches zero. Once this happens the clock is reset to `period_time` and the `stones_per_period` counter is reset. Displays should show the time remaining, and if the user is in overtime then the `stones_per_move` counter should also be shown. **Absolute**: The clock is set to `total_time` and only decreases. **None**: The simplest time control system, no clock is used or displayed. [block:api-header] { "type": "basic", "title": "clock" } [/block] The `clock` field contains the current state of the game clock and changes once per move. [block:code] { "codes": [ { "code": "{\n \n black_time: {\n period_time: 30, /* seconds */\n periods: 5,\n thinking_time: 1200 /* seconds */\n },\n white_time: {\n period_time: 30, /* seconds */\n periods: 5,\n thinking_time: 360.90599999999995 /* seconds */\n },\n current_player: 12751,\n last_move: 1416172879750, /* milliseconds since epoch */\n now: 1416093910807, /* milliseconds since epoch */\n \n start_mode: false, /* removed after a game begins */\n \n \t/* These fields are used by the server, but are not\n * necessary for clients to display clock information */\n game_id: 989449,\n black_player_id: 12751,\n white_player_id: 1, \n title: \"friendly match\",\n paused_since: 1416093910, /* seconds since epoch */\n expiration_delta: 1350000, /* milliseconds */\n expiration: 1416174229750, /* milliseconds since epoch */\n}", "language": "json", "name": "Clock" } ] } [/block] The `black_time` and `white_time` fields take on different forms depending on what time control system is being used [block:code] { "codes": [ { "code": "{\n\tthinking_time: 12345, /* seconds */\n \n /* Used by the server, unnecessary for the client */\n skip_bonus: false\n}", "language": "json", "name": "Fischer" }, { "code": "{\n thinking_time: 12345, /* seconds */\n periods : 3, /* periods left */\n period_time : 30, /* seconds */\n}", "language": "json", "name": "Byo-Yomi" }, { "code": "123455 /* this field is simply a number of seconds on the clock, will be 0 for the player not playing (this is subject to change, and may become number of seconds left on the clock for the last move instead of simply 0 in the future.) */", "language": "json", "name": "Simple" }, { "code": "{\n thinking_time : 12345, /* seconds */\n \n /* applicable only when thinking_time == 0, however \n * the fields will always exist */\n moves_left : 20, /* moves left in this period */\n block_time : 3600 /* seconds left in this period */\n}", "language": "json", "name": "Canadian" }, { "code": "{\n thinking_time: 12345 /* seconds */\n}", "language": "json", "name": "Absolute" }, { "code": "# The `black_time` and `white_time` fields do not exist for the `none` time control.", "language": "text", "name": "None" } ] } [/block] Which is an ugly mess, and we apologize. If we had to do it over again, it'd be a lot different and notably cleaner (or at least that's what we'd like to think.) Details on how to make use of these fields to turn the `clock` into something you can show to your users will follow after the section on `pause_control` [block:api-header] { "type": "basic", "title": "pause_control" } [/block] Games can be paused for several reasons, such as a player having clicked the pause button, the game has been paused for a system event, the game has been paused on the weekend (a correspondence game feature), users are on vacation, or because the game is in the stone removal phase. If the game is paused the game object will contain the `pause_control` field as an object and will contain one or more entries describing what is currently pausing the game. *Note: if a game has been paused and unpaused, the `pause_control` field may still be present in the game data object, but it will contain no fields.* [block:code] { "codes": [ { "code": "{\n \"paused\": {\n \"pauses_left\": 4,\n \"pausing_player_id\": 1\n },\n \"weekend\": true,\n \"system\": true,\n \"vacation-{{player id}}\": true,\n \"stone-removal\": true\n}", "language": "json", "name": "pause_control" } ] } [/block] [block:api-header] { "type": "basic", "title": "Putting it all together" } [/block] Ultimately the goal of understanding the OGS time control system is so you can display a clock showing how much time is left before either a timeout or the start of your next byo-yomi / canadian period. Additionally you have to handle the start clock (which just tells the user how much time is left before the first move must be made), and when to display whether the game is paused or not. The following pseudo-code should help illustrate how to do this - at the end you'll be left with `left` which is intended to be the number of milliseconds left before a timeout / period rollover. [block:code] { "codes": [ { "code": "if clock.start_mode:\n\tDisplay time until clock.expiration\nelif `pause_control` exists and is non-empty:\n Display \"Paused\"\nelse:\n let player_time be black_time or white_time appropriately\n let now_delta = NOW() - clock.now\n let base_time = clock.last_move + now_delta\n if player_time is number:\n \t# simple time\n let time_left = player_time - NOW()\n if player_time is object:\n let left = base_time + player_time.thinking_time*1000 - now\n if moves_left is a field in player_time: # canadian\n \tif left < 0 or player_time.thinking_time == 0:\n \tleft = base_time + (player_time.thinking_time + \\\n player_time.block_time) * 1000 - now\n if periods is a field in player_time: # byo yomi\n if left < 0 or player_time.thinking_time == 0:\n let period_offset = floor((-left / 1000) / player_time.period_time)\n period_offset = max(0, period_offset)\n \n while left < 0:\n \tleft += player_time.period_time * 1000\n \n \n let periods_left = (player_time.periods - period_offset) - 1\n if (player_time.periods - period_offset) - 1 < 0:\n \tleft = 0\n \n\n# left now contains the number of milliseconds left \n# on the clock before either a timeout or the start \n# of the next byo-yomi or canadian period", "language": "text", "name": "Get time left on clock" }, { "code": "# The number of milliseconds since Jan. 1, 1970 (Epoch)", "language": "text", "name": "NOW()" } ] } [/block]