A project developed as part of the Levi9 cloud hackathon. The application enables management of players, teams, and matches, providing APIs for creating and retrieving these entities. Built with modern web technologies to showcase efficiency and scalability.
As part of the solution, an Azure Function was implemented to automatically store match data as match.json files in Azure Blob Storage, enabling efficient and serverless data persistence. The entire cloud infrastructure was provisioned using Infrastructure as Code (IaC), ensuring consistency and repeatability across environments. Additionally, CI/CD pipelines were set up to automate the build, test, and deployment processes for both the application and the infrastructure, supporting rapid and reliable delivery.
-
Install .NET SDK:
Download and install the .NET SDK 9.0 for your operating system from here. -
Verify installation:
Run the following command in your terminal to confirm:dotnet --list-sdks
-
Clone the project:
git clone https://github.com/Acile067/5_days_in_the_clouds_2024_azure.git cd 5_days_in_the_clouds_2024-api/5_days_in_the_clouds_2024.API -
Dotnet CLI API:
dotnet run
The application will run on port 7030.
-
Dotnet CLI AZ-Function:
cd 5_days_in_the_clouds_2024-az-functions/MatchStorage.Function/MatchStorage.Function dotnet runThe function will run on port 7132.
Navigate to https://localhost:7030/scalar/v1 to access a user-friendly interface for API exploration and testing.
-
GET
/players
Retrieves a list of all players. -
GET
/players/{id}
Retrieves details of a specific player by ID. -
POST
/players/create
Creates a new player.
Example request body:{ "nickname": "Player11" }
-
GET
/teams/{id}
Retrieves details of a specific team by ID. -
POST
/teams
Creates a new team.
Example request body:{ "teamName": "Team1", "players": [ "b769b730-d1b9-4a94-8d2d-2936e050722c", "34e7a9e7-df16-4082-92d5-cadb8fc087e5", "64f6186b-3a39-47b9-9313-3fcb8e4f06fd", "187b683c-1255-46a6-a709-60f8af0fd200", "f8987880-8869-472c-8335-83f60132b15d" ] }
-
POST
/matches
Records a new match between two teams.Example request body:
{ "team1Id": "dacfe004-42d8-4938-8e1c-a1fe46739cb6", "team2Id": "7265bc21-46bc-40e3-a2d5-3338c8cc7495", "winningTeamId": "dacfe004-42d8-4938-8e1c-a1fe46739cb6", "duration": 3 }
POST https://localhost:7030/players/create{
"nickname": "Player11"
}HTTP/1.1 200 OK
{
"id": "cb533375-4bfa-4a9d-b89a-c7f850d40ed2",
"nickname": "Player11",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": null,
"ratingAdjustment": null
}GET https://localhost:7030/players/eff975aa-0615-4423-9152-5ab749d95d2cHTTP/1.1 200 OK
{
"id": "eff975aa-0615-4423-9152-5ab749d95d2c",
"nickname": "Player4",
"wins": 1,
"losses": 0,
"elo": 25,
"hoursPlayed": 60,
"teamId": "a10f9801-20cb-446d-8236-881a24a5e683",
"ratingAdjustment": 50
}GET https://localhost:7030/players/{RandomID}HTTP/1.1 404 Not Found
"Player not found"POST https://localhost:7030/teams{
"teamName": "Team1",
"players": [
"b769b730-d1b9-4a94-8d2d-2936e050722c",
"34e7a9e7-df16-4082-92d5-cadb8fc087e5",
"64f6186b-3a39-47b9-9313-3fcb8e4f06fd",
"187b683c-1255-46a6-a709-60f8af0fd200",
"f8987880-8869-472c-8335-83f60132b15d"
]
}
HTTP/1.1 200 OK
{
"id": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"teamName": "Team1",
"players": [
{
"id": "f8987880-8869-472c-8335-83f60132b15d",
"nickname": "Player5",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "34e7a9e7-df16-4082-92d5-cadb8fc087e5",
"nickname": "Player2",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "187b683c-1255-46a6-a709-60f8af0fd200",
"nickname": "Player4",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "b769b730-d1b9-4a94-8d2d-2936e050722c",
"nickname": "Player1",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "64f6186b-3a39-47b9-9313-3fcb8e4f06fd",
"nickname": "Player3",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
}
]
}GET https://localhost:7030/teams/b909d79d-04d3-442d-9b43-29b2a44cc628HTTP/1.1 200 OK
{
"id": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"teamName": "Team1",
"players": [
{
"id": "f8987880-8869-472c-8335-83f60132b15d",
"nickname": "Player5",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "34e7a9e7-df16-4082-92d5-cadb8fc087e5",
"nickname": "Player2",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "187b683c-1255-46a6-a709-60f8af0fd200",
"nickname": "Player4",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "b769b730-d1b9-4a94-8d2d-2936e050722c",
"nickname": "Player1",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
},
{
"id": "64f6186b-3a39-47b9-9313-3fcb8e4f06fd",
"nickname": "Player3",
"wins": 0,
"losses": 0,
"elo": 0,
"hoursPlayed": 0,
"teamId": "b909d79d-04d3-442d-9b43-29b2a44cc628",
"ratingAdjustment": 50
}
]
}POST https://localhost:7030/matches{
"team1Id": "dacfe004-42d8-4938-8e1c-a1fe46739cb6",
"team2Id": "7265bc21-46bc-40e3-a2d5-3338c8cc7495",
"winningTeamId": "dacfe004-42d8-4938-8e1c-a1fe46739cb6",
"duration": 3
}HTTP/1.1 200 OK

