The Mamba project allows a user to host or join a Story Point Planning session and vote on a story.
To get a local copy up and running follow these simple example steps.
Commands are sent between the backend and any front-end application using WebSockets.
A command is sent in the following structure:
Type
|
Description
|
Message
|
START_SESSION
|
Send session name and available cards.
|
{
"sessionName": "Example session",
"availableCards": [
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"autoCompleteVoting": true,
"tags": ["iOS", "Android"],
"password": "Bacon", // optional
}
|
ADD_TICKET
|
Add a new ticket. Changes state to VOTING
|
{
"title": "DM-10000",
"description": "Blah blah",
"selectedTags":["iOS", "Android"]
}
|
SKIP_VOTE
|
Skip vote for a participant
|
{
"participantId": ""
}
|
REMOVE_PARTICIPANT
|
Request to remove a participant from the session
|
{
"participantId": ""
}
|
END_SESSION
|
Closes session and removes all participants
|
None
|
FINISH_VOTING
|
Force state from VOTING to VOTING_FINISHED
|
None
|
REVOTE
|
When in VOTING_FINISHED state revote the current ticket
|
None
|
RECONNECT
|
Reconnect to existing session using a UUID
|
None
|
EDIT_TICKET
|
Edit the details of the existing ticket
|
{
"title": "DM-10000",
"description": "Blah blah",
"selectedTags":["iOS", "Android"]
}
|
ADD_TIMER
|
Add a timer to the session to end voting when the timer ends.
|
{
"time":2
}
|
CANCEL_TIMER
|
Cancel an active timer.
|
None
|
PREVIOUS_TICKETS
|
Request previous tickets that have been voted on.
|
None
|
REQUEST_COFFEE_BREAK
|
Request coffee break break.
|
None
|
Type
|
Description
|
Message
|
NONE_STATE
|
State `NONE` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
}
],
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
VOTING_STATE
|
State `VOTING` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
},
{
"name":"Piet",
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515"
}
],
"ticket":{
"title":"Test",
"ticketVotes":[
{
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9",
"selectedCard":"FIVE",
"tag":"iOS"
}
],
"description":"Test"
},
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
FINISHED_STATE
|
State `VOTING_FINISHED` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
},
{
"name":"Piet",
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515"
}
],
"ticket":{
"title":"Test",
"ticketVotes":[
{
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9",
"selectedCard":"FIVE"
"tag":"iOS"
},
{
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515",
"selectedCard":null, //Indicates that this vote is skipped
"tag":null
}
],
"description":"Test"
},
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
INVALID_COMMAND
|
Inform client that command sent is invalid
|
{
"code":"0000",
"description":"No session code has been specified"
}
|
PREVIOUS_TICKETS
|
Response that contains previous tickets that have been voted on.
|
{
"previousTickets":[
{
"title":"Test",
"ticketVotes":[
{
"participantId":"D520EFDD-C4BD-450B-9531-30E404B77D0F",
"selectedCard":"FIVE",
"tag":"iOS"
}
],
"description":""
}
]
}
|
SESSION_IDLE_TIMEOUT
|
Response that indicates that the session has timed out because it was idle.
|
|
Type
|
Description
|
Message
|
JOIN_SESSION
|
Join session with specified sessionCode, user name, and password.
|
{
"participantName":"Armand",
"sessionCode":"545544",
"password":"Bacon" //optional
}
|
VOTE
|
Send vote value for a ticket
|
{
"selectedCard":"ONE",
"tag":"iOS"
}
|
LEAVE_SESSION
|
Inform server client is disconnecting
|
None
|
RECONNECT
|
Reconnect to existing session using a UUID
|
None
|
CHANGE_NAME
|
Change participant's name. Will fail if not the matching participant UUID.
|
{
"name":"TestName"
}
|
REQUEST_COFFEE_BREAK
|
Request coffee break break.
|
None
|
Type
|
Description
|
Message
|
NONE_STATE
|
State `NONE` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
}
],
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
VOTING_STATE
|
State `VOTING` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
},
{
"name":"Piet",
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515"
}
],
"ticket":{
"title":"Test",
"ticketVotes":[
{
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9",
"selectedCard":"FIVE",
"tag":"iOS"
}
],
"description":"Test"
},
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
FINISHED_STATE
|
State `VOTING_FINISHED` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
},
{
"name":"Piet",
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515"
}
],
"ticket":{
"title":"Test",
"ticketVotes":[
{
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9",
"selectedCard":"FIVE",
"tag":"iOS"
},
{
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515",
"selectedCard":null, //Indicates that this vote is skipped
"tag": null
}
],
"description":"Test"
},
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
INVALID_COMMAND
|
Inform client that command sent is invalid
|
{
"code":"0000",
"description":"No session code has been specified"
}
|
INVALID_SESSION
|
Inform client that session is invalid
|
None
|
REMOVE_PARTICIPANT
|
Inform client that they have been removed from the session
|
None
|
END_SESSION
|
Inform client that session had been ended
|
None
|
SESSION_IDLE_TIMEOUT
|
Response that indicates that the session has timed out because it was idle.
|
|
Type
|
Description
|
Message
|
NONE_STATE
|
State `NONE` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
}
],
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
VOTING_STATE
|
State `VOTING` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
},
{
"name":"Piet",
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515"
}
],
"ticket":{
"title":"Test",
"ticketVotes":[
{
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9",
"selectedCard":"FIVE",
"tag":"iOS"
}
],
"description":"Test"
},
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
FINISHED_STATE
|
State `VOTING_FINISHED` command containing current state of session
|
{
"participants":[
{
"name":"Armand",
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9"
},
{
"name":"Piet",
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515"
}
],
"ticket":{
"title":"Test",
"ticketVotes":[
{
"participantId":"852ACB12-4B40-4BC2-B72B-17057A1A5AE9",
"selectedCard":"FIVE",
"tag":"iOS"
},
{
"participantId":"34ED510B-B21D-423E-83D0-B85747F4D515",
"selectedCard":null, //Indicates that this vote is skipped
"tag":null
}
],
"description":"Test"
},
"availableCards":[
"ZERO", "ONE", "TWO", "THREE", "FIVE", "EIGHT", "THIRTEEN", "TWENTY", "FOURTY", "HUNDRED", "QUESTION"
],
"sessionCode":"000000",
"sessionName":"Test"
}
|
INVALID_COMMAND
|
Inform client that command sent is invalid
|
{
"code":"0000",
"description":"No session code has been specified"
}
|
INVALID_SESSION
|
Inform client that session is invalid
|
None
|
END_SESSION
|
Inform client that session had been ended
|
None
|
SESSION_IDLE_TIMEOUT
|
Response that indicates that the session has timed out because it was idle.
|
|
White lines indicate completed features.
Distributed under the MIT License. See LICENSE
for more information.
mamba-backend-vapor
Table of Contents
About The Project
Description
This is the backend companion for Mamba iOS
The Mamba project allows a user to host or join a Story Point Planning session and vote on a story.
Built With
Getting Started
To get a local copy up and running follow these simple example steps.
Prerequisites
Installation
Usage
Swift Package Manager
Build package:
Test package:
Update or resolve package dependencies:
Docker
To run the container:
Commands
Commands are sent between the backend and any front-end application using WebSockets. A command is sent in the following structure:
Planning Sequence Diagram
Planning Host
Client to server
VOTING
VOTING
toVOTING_FINISHED
VOTING_FINISHED
state revote the current ticketServer to client
Planning Join
Client to server
Server to client
Planning Spectate
Client to server
Server to client
Error codes
Invalid Session
0001
: The specified session code doesn’t exist or the password provided is invalid.Invalid Command
0000
: No session code has been specified.0002
: The command doesn’t exist.0003
: The server has run out of capacity, could not create a new planning session.0004
: Invalid identifier.0005
: Invalid parameters.0006
: Invalid state.Session timeout
0007
: Session idle timeoutRoadmap
White lines indicate completed features.
License
Distributed under the MIT License. See
LICENSE
for more information.Contact
Armand Kamffer - @Armgame - kamffer1@gmail.com