{"id":17099702,"url":"https://github.com/halilb/tombala","last_synced_at":"2026-04-28T22:35:42.016Z","repository":{"id":69722811,"uuid":"48958799","full_name":"halilb/tombala","owner":"halilb","description":null,"archived":false,"fork":false,"pushed_at":"2016-01-12T13:37:32.000Z","size":32,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-06T08:57:08.794Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/halilb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-03T19:58:19.000Z","updated_at":"2020-04-24T08:47:37.000Z","dependencies_parsed_at":"2023-03-10T07:15:57.316Z","dependency_job_id":null,"html_url":"https://github.com/halilb/tombala","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/halilb/tombala","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilb%2Ftombala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilb%2Ftombala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilb%2Ftombala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilb%2Ftombala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/halilb","download_url":"https://codeload.github.com/halilb/tombala/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilb%2Ftombala/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32402672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T19:38:08.556Z","status":"ssl_error","status_checked_at":"2026-04-28T19:37:55.688Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T15:11:08.605Z","updated_at":"2026-04-28T22:35:41.999Z","avatar_url":"https://github.com/halilb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Tombala Game\n===========================\n\n# INSTRUCTIONS\n\n* Clone this repo.\n* Run *python server/main.py* to run the server.\n* Run *python client/main.py* to run the client.\n* /login {username} to set user name.\n* /create {roomname} {countdown} to create a new room. Game will start after {countdown} seconds.\n* /join {roomname} to join a game.\n* /rooms to display existing rooms.\n* /quit to quit a game.\n* /mark {number} if you have the number in your playcard.\n* /cinko {total} to announce your new cinko.\n* Click *Next Number* button to request new number. A new number will be distributed when all users in the room declare they are ready.\n\n# PROTOCOL\n\n*Tombola* is a board game originated in Italy. In Turkey, it is called *Tombala* and traditionally played in new year's eve. It's similar to *bingo* game.\n\n![Tombala game card image](https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Tombola.jpg/320px-Tombola.jpg)\n\nThis document defines functional requirements for a simple tombala game and offers a simple text-based protocol desing which will be used for communication between Tombala Clients and Tombala Server. The protocol is designed to run on top of the TCP.\n\nThis protocol is designed to support multiple *tombala* sessions simultaneously.\n\n# 1. Functional Requirements\n\n#### 1.1. Client-Server Connection\n\nUser connects to the Tombala Server through any Tombala Client by providing a user name. User name shall be unique across the Tombala server.\n\nUser shall be removed from all games when he loses internet connection. Timeout shall be 30 seconds.\n\n#### 1.2. Game Rooms\n\n##### 1.2.1. Creating a game room\n\nThe system shall support multiple games simultaneously.\n\nEvery user shall be able to create a new game room. User shall provide a countdown value to arrange start date of the game. Game starts after coundown interval ends.\n\n##### 1.2.2. Displaying game rooms\n\nUser shall display existing rooms.\n\n##### 1.2.3. Joining a game room\n\nUser shall join a game room by providing the room's name.\nUser shall receive an error:\n* If the game has already started.\n* If user is already in another game room.\n\n##### 1.2.4. Quiting a game room\n\nUser shall quit a game room before the game finishes. He can then join any other game if the game is not started.\n\n#### 1.3. The Game\n\nA game card contains three rows and five numbers on each row. It is randomly generated and distributed when the game starts.\n\nA new number should be randomly generated distributed when all users want to proceed to the next turn. This number should be between 1 and 90. User checks whether he has the number for the current turn and proceeds. The game should be on hold until all users proceed to the next turn.\n\nWhen a user marks every number in a row of the game card, he should announce it as *cinko*. This claim must be validated and distributed to the other users. Users are responsible for following the numbers and announcing cinkos. Game is over when a user achieves three *cinkos*.\n\n\n# 2. MESSAGE FORMAT\n\nAll protocol messages have to contain a keyword which describes the type of the message. This keyword will be called as the header of the message.\n\nProtocol messages contain body field as the content. The format of the body message is Javascript Object Notation(JSON). You can find JSON format documentation here: http://json.org/\n\nHeader keyword and and body message is seperated with a colon character.\n\n    {HEADER_KEYWORD}:{BODY_MESSAGE}\n\nThere are two general types of communication:\n\n1. After user actions, client issues a request with relevant header and server responses with an error or success header.\n\n2. When state changes on the server, it broadcasts messages to related clients.\n\nAll messages shall close with a line break character \\n.\n\n## 2.1. Client Request Format\n\nTombala clients are responsible for adding a request identifier to the body message. The identifier is added to the response body by the server, and client uses that to correspond server responses with the relavant request. The identifier will be called as sequence number.\n\nSequence numbers are integers generated on the client side. They are not manipulated but simply echoed in responses.\n\n**Client Request Types**\n\n- CHBEAT: Client Heartbeat\n- CLOGIN: Client Login\n- CCROOM: Client Create Room\n- CLROOM: Client List Rooms\n- CJROOM: Client Join Room\n- CQROOM: Client Quit Room\n- CCINKO: Client Cinko\n- CNNMBR: Client Next Number\n\n**Server Response Types for Client Requests**\n\n- SSUCCS: Server response with success\n- SERROR: Server response with error\n\n## 2.2. Server Broadcast Format\n\nServer broadcasts messages about a room to the connected clients when state changes for the room.\n\n- BGCARD: Broadcast Game Card\n- BNUMBR: Broadcast New Number\n- BCINKO: Broadcast Cinko\n- BUSRLS: Broadcast User List\n\n# 3.1. Client Requests\n\n#### CHBEAT : Client Heartbeat\n\nClient heartbeat message is just used to inform the server that the client is still connected.\n\n*CHBEAT* messages are expected to be sent regularly while the client is online. Expected interval time is 10 seconds. Client will be considered as disconnected when there is no heartbeat in the last 30 seconds. Disconnected clients will be removed from their active tombala rooms and game continues in those rooms.\n\nExample Request:\n\n    CHBEAT:{\n        \"seq\": 111\n    }\n\nExample Response:\n\n    SSUCCS:{\n        \"seq\": 111\n    }\n\n#### CLOGIN: Client Login\n\n*CLOGIN* is used to set a username for client connection. This request is needed to authenticate the client on the server and it must be issued before any other request.\n\nRequest fields:\n\n- **username**(string): It should be unique across the system.\n\nExample request:\n\n    CLOGIN:{\n        \"seq\": 111,\n        \"username\": \"user1\"\n    }\n\nExpected responses: SSUCCS, SERROR\n\nExpected response fields:\n\n- **message**(string): Description text for SSUCCS or SERROR\n\nSuccess response example:\n\n    SSUCCS:{\n        \"seq\": 111,\n        \"message\": \"Welcome user1!\"\n    }\n\nError response example:\n\n    SERROR:{\n        \"seq\": 111,\n        \"message\": \"user1 already exists on the system. Please choose another username!\"\n    }\n\n#### CCROOM: Client Create Room\n\n*CCROOM* is used to create a new game room.\n\nRequest fields:\n\n- **roomname**(*string*): An alias for the tombala session room. It needs to be unique across the system.\n- **countdown**(*integer*) : This parameter should be defined as seconds. It is used to calculate the starting date of the game. \n\nExample request:\n\n    CCROOM:{\n        \"seq\": 111,\n        \"roomname\": \"room1\",\n        \"countdown\": 120 // 2 minutes\n    }\n\nExpected responses: SSUCCS, SERROR\n\nExpected response fields:\n\n- **message**(*string*): Description text for SSUCCS or SERROR\n\nSuccess response example:\n\n    SSUCCS:{\n        \"seq\": 111,\n        \"message\": \"room1 is created!\"\n    }\n\nError response example:\n\n    SERROR:{\n        \"seq\": 111,\n        \"message\": \"room1 already exists!\"\n    }\n    \n    \n    \n#### CLROOM: Client List Rooms\n \n*CLROOM* is used to retrieve existing game rooms.\n\nThis request does not need additional body parameters.\n\nExample request:\n\n    CLROOM:{\n        \"seq\": 111\n    }\n\nExpected response: SSUCCS\n\nExpected response fields:\n\n* **rooms**(*array*): This field contains a collection with Room objects.\n* **room.roomname**(*string*): Alias for the room.\n* **room.startTime**(*date*): Starting date of the game. It is defined in seconds.\n* **room.userlist**(*array*): Contains user names of current users in the room.\n\nResponse example:\n\n    SSUCCS:{\n        \"seq\": 111,\n        \"rooms\": [{\n        \t\"roomname\": \"room1\",\n            \"startTime\": \"2016-01-10 19:22:51.899637\",\n            \"userlist\": [\"user1\", \"user2\"]\n        }, {\n            \"roomname\": \"room2\",\n            \"startTime\": \"2016-01-10 19:23:51.899637\"\n            \"userlist\": [\"user3\", \"user4\"]\n        }]\n    }\n    \n#### CJROOM: Client Join Room\n\n*CJROOM* is used to join a game room.\n\nClients can not join a room if they are already in another room. For such scenarios, *CQROOM* request must be issued before *CJROOM*.\n\nRequest fields:\n\n- **roomname**(*string*): Room name.\n\nExample request:\n\n    CJROOM:{\n        \"seq\": 111,\n        \"roomname\": \"room1\"\n    }\n\nExpected responses: SSUCCS, SERROR\n\nExpected response fields:\n\n- **message**(*string*): Description text for SSUCCS or SERROR\n\nSuccess response example:\n\n    SSUCCS:{\n        \"seq\": 111,\n        \"message\": \"Joined room1 successfully!\"\n    }\n\nError response example:\n\n    SERROR:{\n        \"seq\": 111,\n        \"message\": \"room1 does not exist!\"\n    }\n    \n#### CQROOM: Client Quit Room\n\n*CQROOM* is used to quit from user's current game room.\n\nExample request:\n\n    CQROOM:{\n        \"seq\": 111,\n    }\n\nExpected responses: SSUCCS, SERROR\n\nExpected response fields:\n\n- **message**(*string*): Description text for SSUCCS or SERROR\n\nSuccess response example:\n\n    SSUCCS:{\n        \"seq\": 111,\n        \"message\": \"You've left room1 successfully!\"\n    }\n\nError response example:\n\n    SERROR:{\n        \"seq\": 111,\n        \"message\": \"You already aren't in a room currently!\"\n    }\n    \n#### CCINKO: Client Cinko\n\nCCINKO is used announce cinko. Server validates client's cinko claim and broadcasts it to all connected clients in the room.\n\nThis request takes a **total** parameter in the body. The game is over when a client has three cinkos.\n\nRequest fields:\n\n- **total**(*integer*): Total cinko count. Minimum 1, maximum 3.\n\nExample request:\n\n    CCINKO:{\n        \"seq\": 111,\n        \"cinko\": 3 // wins the game\n    }\n\nExpected responses: SSUCCS, SERROR\n\nExpected response fields:\n\n- **message**(*string*): Description text for SSUCCS or SERROR\n\nSuccess response example:\n\n    SSUCCS:{\n        \"seq\": 111,\n        \"message\": \"Congratulations!\"\n    }\n\nError response example:\n\n    SERROR:{\n        \"seq\": 111,\n        \"message\": \"Your cinko claim is wrong!\"\n    }\n    \n#### CNNMBR: Client Next Number\n\n*CNNMBR* is used to inform server that the client is ready for a new number. It is client's responbisility to check his game card after receiving a new number. After checking the game card, clients have to issue *CNNMBR* request. Game will not proceed until all participating users send a *CNNMBR* request.\n\nExample request:\n\n    CNNMBR:{\n        \"seq\": 111\n    }\n\nExpected responses: SSUCCS, SERROR\n\nExpected response fields:\n\n- **message**(*string*): Description text for SSUCCS or SERROR\n\nSuccess response example:\n\n    SSUCCS:{\n        \"seq\": 111,\n        \"message\": \"Next number will be broadcasted when everyone proceeds!\"\n    }\n\nError response example:\n\n    SERROR:{\n        \"seq\": 111,\n        \"message\": \"You've already proceeded for the current turn!\"\n    }\n    \n# 3.2. Server Broadcasts\n\nBroadcast messages are issued from server when the room's state changes. Clients are subscribed to those broadcast messages when they join the room.\n\n#### BGCARD: Broadcast Game Card\n\nThis message is broadcasted when the game starts in the room.\n\nMessage fields:\n\n- **gamecard**(*array*): It has three rows represeting rows in an actual game card.\n- **gamecard.row**(*array*): Every row has five integer numbers between 1 and 90. Clients shall use this field to determine cinkos. \n\nExample message:\n\n    BGCARD:{\n        \"gamecard\": [\n          [[77, 1, 18, 4, 43],\n          [6s1, 27, 25, 16, 56],\n          [46, 80, 31, 73, 45]]\n        ]\n    }\n    \n#### BNUMBR: Broadcast New Number\n\n*BNUMBR* is broadcasted when a new number is generated on the server for a new turn.\n\nMessage fields:\n\n- **number**(*integer*): A random number generated on the server. Minimum 1, maximum 90. Generated numbers must be unique for any given game session. Clients use this number to mark their game cards. Clients have to issue *CNEXT* request using this number as a parameter for proceeding to next turn.\n\nExample message:\n\n    BNUMBR:{\n        \"number\": 66\n    }\n    \n#### BCINKO: Broadcast Cinko\n\n*BCINKO* is broadcasted when a user achieves a new cinko. A game is over when any user has three cinkos. Clients shall use this information to let the user know when the game is over.\n\nMessage fields:\n\n- **username**(*string*): Username for the new cinko's owner.\n- **total**(*integer*): User's total cinko count with the new cinko. Minimum 1, maximum 3. User wins the game when it is 3.\n\nExample message:\n\n    BCINKO:{\n        \"username\": \"user1\",\n        \"total\": 3 // user1 wins the game\n    }\n    \n#### BUSRLS: Broadcast User List\n\n*BUSRLS* broadcasts user list for the current room. It is broadcasted every time a new user attends or leaves the game. It is client's responsibility to check differences in the list to determine incoming or leaving users.\n\nMessage fields:\n\n- **userlist**(*array*): A collection for usernames.\n\nExample message:\n\n    BUSRLS:{\n        \"userlist\": [\"user1\", \"user2\", \"user4\"]\n    }\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalilb%2Ftombala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhalilb%2Ftombala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalilb%2Ftombala/lists"}