{"id":24642417,"url":"https://github.com/alexadam/sport-stats","last_synced_at":"2025-05-12T17:28:58.909Z","repository":{"id":35631654,"uuid":"39905675","full_name":"alexadam/sport-stats","owner":"alexadam","description":"Sport stats UI components","archived":false,"fork":false,"pushed_at":"2016-11-07T13:15:39.000Z","size":2975,"stargazers_count":71,"open_issues_count":0,"forks_count":18,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-15T03:03:45.809Z","etag":null,"topics":["3d","react","soccer","sport-stats","sports","sports-data","sportsanalytics","threejs","ui","ui-components"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexadam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-29T17:05:09.000Z","updated_at":"2025-02-11T15:05:36.000Z","dependencies_parsed_at":"2022-08-17T21:40:36.175Z","dependency_job_id":null,"html_url":"https://github.com/alexadam/sport-stats","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexadam%2Fsport-stats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexadam%2Fsport-stats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexadam%2Fsport-stats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexadam%2Fsport-stats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexadam","download_url":"https://codeload.github.com/alexadam/sport-stats/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253786810,"owners_count":21964236,"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":["3d","react","soccer","sport-stats","sports","sports-data","sportsanalytics","threejs","ui","ui-components"],"created_at":"2025-01-25T13:11:37.738Z","updated_at":"2025-05-12T17:28:58.854Z","avatar_url":"https://github.com/alexadam.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sport Stats\nSport stats UI components (react components + three, d3)\n\n[**Demo**](https://alexadam.github.io/demos/sport-stats/)\n\n![alt ex1.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex1.png?raw=true)\n\n## How to use\n\n```\nnpm install https://github.com/alexadam/sport-stats\n# or downlod/clone this repository\n```\n\n```\nimport {LiveEvents, LiveEvent, Field2D, Field3D, PlayerDetails, GameStats, TeamsTable, FieldPlay} from 'sport-stats';\n```\n\nYou can find a demo project in the 'example-project' directory.\n\n# Components\n\n## 3D Field\n\n```\n\u003cField3D field={this.soccerField} onPlayerClick={this.playerClick} homeTeam={this.homeTeam} awayTeam={this.awayTeam} shouldUpdate={this.state.shouldUpdate} /\u003e\n```\n\n```\nhomeTeam = {\n    id: 1,\n    name: 'Home Team',\n    logoUrl: '/textures/team1.png',\n    playerPositionById: [\n        [1],\n        [2, 3, 4, 5],\n        [6, 7],\n        [8, 9, 10],\n        [11]\n    ],\n    players: [\n        {\n            id: 1,\n            name: 'Home Player 1',\n            tShirtImgUrl: '/textures/tshirt5.png',\n            tShirtNr: '1',\n            faceImgUrl: '/textures/generic-face.png'\n        },\n        {\n            id: 2,\n            name: 'Home Player 2',\n            tShirtImgUrl: '/textures/tshirt5.png',\n            tShirtNr: '2',\n            faceImgUrl: '/textures/generic-face.png'\n        },\n        ...........\n```\n\n![alt ex2.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex2.png?raw=true)\n\n### Multiple textures\n\n```\nsoccerField = {\n    width: 105,\n    height: 68,\n    textureUrl: 'textures/soccer.png'\n}\niceHockeyField = {\n    width: 68 * 2.15,\n    height: 68,\n    textureUrl: 'textures/icehockey.png'\n}\nbasketball = {\n    width: 89,\n    height: 51,\n    textureUrl: 'textures/basketball.png'\n}\n```\n\n![alt ex3.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex3.png?raw=true)\n\n\n## 2D Field\n\n```\n\u003cField2D field={this.soccerField2D} onPlayerClick={this.playerClick} perspective=\"true\" homeTeam={this.homeTeam} awayTeam={this.awayTeam}  shouldUpdate={this.state.shouldUpdate}/\u003e\n```\n\n```\nsoccerField2D = {\n    width: 1200,\n    height: 780,\n    textureUrl: 'textures/soccer.png'\n}\n```\n\n![alt ex4.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex4.png?raw=true)\n![alt ex41.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex41.png?raw=true)\n\n## Live Events\n\n```\n\u003cLiveEvents homeTeam={this.homeTeam} awayTeam={this.awayTeam} matchData={this.matchData}\u003e\n    {this.eventsData.map((event, i) =\u003e \u003cLiveEvent type={event.players[0].teamId === 1 ? 'home' : 'away'} {...event} key={i} onPlayerClick={this.playerClick}/\u003e)}\n\u003c/LiveEvents\u003e\n```\n\n```\nmatchData = {\n    score: '2 - 1',\n    time: '86\\''\n}\n\neventsData = [{\n    logoUrl: '/textures/yellow-card.png',\n    time: '82\\'',\n    players: [\n        {\n            id: 1,\n            teamId: 1,\n            name: 'Home Player 1'\n        }\n    ]\n},\n{\n    logoUrl: '/textures/change2.png',\n    time: '71\\'',\n    players: [\n        {\n            id: 1,\n            teamId: 1,\n            name: 'Home Player 1'\n        },\n        {\n            id: 2,\n            teamId: 1,\n            name: 'Home Player 2'\n        }\n    ]\n},\n...........\n```\n\n![alt ex5.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex5.png?raw=true)\n\n## Game Stats\n\n```\n\u003cGameStats stats={this.gameStats} homePlayers={this.homeTeam.players} awayPlayers={this.awayTeam.players} onPlayerClick={this.playerClick} fieldTextureUrl=\"/textures/soccer-field.svg\" possesionData={this.possesionData}/\u003e\n\n```\n\n```\ngameStats = [\n    {\n        type: 'Total Shots',\n        home: '17',\n        away: '12'\n    },\n    {\n        type: 'Shots On Target',\n        home: '5',\n        away: '7'\n    },\n    {\n        type: 'Pass Accuracy',\n        home: '75%',\n        away: '86%'\n    },\n    {\n        type: 'Aerial Won',\n        home: '70%',\n        away: '30%'\n    },\n    ....\n\npossesionData = {\n        type: 'Possesion',\n        home: '60%',\n        away: '40%'\n    };\n```\n\n![alt ex6.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex6.png?raw=true)\n\n## Player Details\n\n```\n\u003cPlayerDetails player={this.state.playerData} bio={this.state.playerBioData} stats={this.state.playerStateData} /\u003e\n```\n\n```\nplayerBioData: {\n    'Age': '29',\n    'Height': '1.85 cm',\n    'Weight': '73 kg',\n    'Nationality': 'German'\n},\nplayerStateData:  {\n    'Total Goals': '1',\n    'Goal Assists': '1',\n    'Shots On Target': '3',\n    'Total Shots': '3',\n    'Fouls Committed': '1',\n    'Fouls Suffered': '2',\n    'Red Cards': '0',\n    'Yellow Cards': '1'\n}\n```\n\n![alt ex7.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex7.png?raw=true)\n\n\n## Field Play (work in progress)\n\n```\n\u003cFieldPlay field={this.soccerField} onPlayerClick={this.playerClick} shouldUpdate={this.state.shouldUpdate} objects={this.FPObjects} arrows={this.FPArrows}/\u003e\n```\n\n```\nFPObjects = [\n    {\n        x: 50,\n        y: 30,\n        data: {\n            // TODO\n            id: 1,\n            name: 'Away Player 1',\n            tShirtImgUrl: '/textures/tshirt9.png',\n            tShirtNr: '1',\n            faceImgUrl: '/textures/generic-face.png'\n        }\n    },\n    {\n        x: 75,\n        y: 45,\n        data: {\n            id: 2,\n            name: 'Away Player 2',\n            tShirtImgUrl: '/textures/tshirt9.png',\n            tShirtNr: '2',\n            faceImgUrl: '/textures/generic-face.png'\n        }\n    },\n    .....\n\nFPArrows = [\n    {\n        start: [50, 30, 0],\n        middle: [62, 37, 20],\n        end: [75, 45, 0],\n        color: 0x0000ff,\n        lineWidth: 3\n    },\n    ....\n    {\n        start: [85, 20, 0],\n        end: [100, 35, 2],\n        color: 0xff0000,\n        lineWidth: 3\n    }\n    ......\n```\n\n![alt ex8.png](https://github.com/alexadam/sport-stats/blob/master/ex-imgs/ex8.png?raw=true)\n\n## Credits\nExample images from:\n * https://pixabay.com\n * https://en.wikipedia.org/wiki/File:Icehockeylayout.svg\n * https://en.wikipedia.org/wiki/File:Basketball_court_fiba.svg\n * https://commons.wikimedia.org/wiki/File:Soccer_Field_Transparant.svg\n\n## TODO\n * problems when resizing the 3d components\n * finish 'FieldPlay' \u0026 'TeamsTable' + add more (ex. heatmaps, graphs etc.)\n * more responsive components\n * add a server example with live update\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexadam%2Fsport-stats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexadam%2Fsport-stats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexadam%2Fsport-stats/lists"}