{"id":17668548,"url":"https://github.com/evanshortiss/shipwars-streams","last_synced_at":"2025-08-21T14:04:21.888Z","repository":{"id":66153987,"uuid":"372612602","full_name":"evanshortiss/shipwars-streams","owner":"evanshortiss","description":"A collection of Kafka Streams services that use data generated by arcade.redhat.com/shipwars","archived":false,"fork":false,"pushed_at":"2022-02-14T15:31:15.000Z","size":12251,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-08T22:14:57.771Z","etag":null,"topics":["java","kafka","kafka-streams","quarkus"],"latest_commit_sha":null,"homepage":"","language":"Java","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/evanshortiss.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-31T19:43:38.000Z","updated_at":"2022-02-14T15:31:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"f929606d-b79b-4135-83a5-33b771675d11","html_url":"https://github.com/evanshortiss/shipwars-streams","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/evanshortiss/shipwars-streams","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fshipwars-streams","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fshipwars-streams/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fshipwars-streams/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fshipwars-streams/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evanshortiss","download_url":"https://codeload.github.com/evanshortiss/shipwars-streams/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fshipwars-streams/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261798704,"owners_count":23211245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["java","kafka","kafka-streams","quarkus"],"created_at":"2024-10-23T23:22:58.217Z","updated_at":"2025-06-25T03:33:55.341Z","avatar_url":"https://github.com/evanshortiss.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shipwars Streams\n\nJava application that uses [Quarkus](https://quarkus.io/) and [Apache Kafka Streams](https://kafka.apache.org/documentation/streams)\nto analyse events sent to Kafka by the [Shipwars Game Server](https://github.com/redhat-gamedev/shipwars-game-server).\n\n## Streams Topologies\n\n* _shot-stream-enricher_ - Joins shot event data with the associated player data. This enriched topic is used by the _shot-distribution-aggregator_.\n* _match-aggregator_ - Creates an aggregate record for each match. This facilitates match analysis and replay.\n* _shot-distribution-aggregator_ - Aggregates the distribution of shots for given game generations (each game server deployment is a new generation).\n\n\u003cdiv align=\"center\"\u003e\n\t\u003cbr\u003e\n    \u003cimg style=\"max-width: 600px;\" src=\"assets/architecture-complete.png\"/\u003e\n\t\u003cbr\u003e\n  \u003ci\u003eArchitecture of the overall application and Quarkus Kafka Streams Topology.\u003c/i\u003e\n  \u003cbr\u003e\n  \u003cbr\u003e\n\u003c/div\u003e\n\nThe _match-aggregator_ exposes the following endpoint:\n\n* `GET /replays` - Returns an array of replays. A `count` query parameter can\nbe provided to limit the returned results - it defaults to 12.\n\nThe _shot-distribution-aggregator_ exposes the following endpoints:\n\n* `GET /shot-distribution` - Returns the shot distribution for all game generations in JSON format.\n* `GET /shot-distribution/stream` - Opens a HTTP Server-Sent Events stream that sends each enriched shot to the HTTP client.\n\nThe shot distribution JSON response contains top-level game generation keys,\nand within these are the hit/miss counts for each cell and each player type.\n\n```js\n{\n  \"a-unique-game-uuid\": {\n    \"0,0\": {\n      \"ai_hit\": 6,\n      \"ai_miss\": 2,\n      \"human_hit\": 3,\n      \"human_miss\": 5\n    },\n     \"0,1\": {\n      \"ai_hit\": 1,\n      \"ai_miss\": 6,\n      \"human_hit\": 2,\n      \"human_miss\": 5\n    }\n    // Data for every cell on the 5x5 grid, i.e up to key \"4,4\"...\n  },\n  \"another-unique-game-uuid\": { /* Data for all cells in that game */ }\n}\n```\n\n## Use with OpenShift Streams for Apache Kafka\n\nEach module is configured to use SASL SSL to connect to Kafka, since this is\nstandard with OpenShift Streams for Apache Kafka.\n\n```bash\n# Get the bootstrap URL using the rhoas CLI. A client ID and secret can be\n# obtained using the rhoas CLI or cloud.redhat.com UI\n# Specify which application to run using the -f flag\nKAFKA_BOOTSTRAP_SERVERS=$(rhoas kafka describe | jq .bootstrapServerHost -r) \\\nKAFKA_CLIENT_ID=\"replace-me\" \\\nKAFKA_CLIENT_SECRET=\"replace-me\" \\\n./mvnw quarkus:dev -f shot-distribution-aggregator/pom.xml\n```\n\n## Running Locally\n\nRefer to the Docker/Podman guides in [Shipwars Deployment](https://github.com/redhat-gamedev/shipwars-deployment).\nFor example to run Shipwars services using Docker:\n\n```bash\nKAFKACONNECTION_BOOTSTRAPSERVERS=$(rhoas kafka describe | jq .bootstrapServerHost -r) \\\nKAFKACONNECTION_SSL=true \\\nKAFKACONNECTION_USER=\"replace-me\" \\\nKAFKACONNECTION_PASSWORD=\"replace-me\" \\\ndocker-compose up --force-recreate --build\n```\n\nNext, start each Kafka Streams module by targeting the necessary `pom.xml`:\n\n```bash\n# Get the bootstrap URL using the rhoas CLI. A client ID and secret can be\n# obtained using the rhoas CLI or cloud.redhat.com UI\nKAFKA_BOOTSTRAP_SERVERS=$(rhoas kafka describe | jq .bootstrapServerHost -r) \\\nKAFKA_CLIENT_ID=\"replace-me\" \\\nKAFKA_CLIENT_SECRET=\"replace-me\" \\\n./mvnw quarkus:dev -f shot-distribution-aggregator/pom.xml\n```\n\n*Note: The _shot-distribution-aggregator_ relies on the _shot-stream-enricher_ for data, so you need to run both.*\n\n## Building\n\n### JAR files\n\nThis will build both application module JARs.\n\n```bash\nmvn clean install\n```\n\n### Docker Images\n\nEach module contains a script folder. Run the `build.sh` script from the root\nof the module you'd like to build:\n\n```bash\n# These will use defaults if not provided\nIMAGE_TAG=latest \\\nIMAGE_REPOSITORY=quay.io/yourusername/name-of-image \\\n./scripts/build.sh\n```\n\nTo push the image use the `push.sh`:\n\n```bash\n# These will use defaults if not provided\nIMAGE_TAG=latest \\\nIMAGE_REPOSITORY=quay.io/yourusername/name-of-image \\\n./scripts/push.sh\n```\n\n## Running for Development\n\nFollow the guide above to run the associated services using Docker/Podman, but\nremove this service from the Dockerfile, i.e start all of the services using\n`docker-compose up` except this one.\n\nOnce the other services have started, you can start this one using:\n\n```bash\nQUARKUS_KAFKA_STREAMS_BOOTSTRAP_SERVERS=localhost:9094 \\\nKAFKA_BOOTSTRAP_SERVERS=localhost:9094 \\\nQUARKUS_HTTP_PORT=8585 \\\n./mvnw quarkus:dev -f shot-distribution-aggregator/pom.xml\n```\n\n## Scaling\n\nKafka Streams pipelines can be scaled out, i.e. the load can be distributed\namongst multiple application instances running the same pipeline.\n\nThis particular example has not been designed to support this functionality.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanshortiss%2Fshipwars-streams","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevanshortiss%2Fshipwars-streams","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanshortiss%2Fshipwars-streams/lists"}