Smart Contract
TeamAssignment
A.8d75e1dff5f8af66.TeamAssignment
1// TeamAssignment.cdc
2// Smart contract for randomly assigning NBA Top Shot usernames to NBA teams
3// Uses Flow's on-chain randomness (revertibleRandom)
4
5access(all) contract TeamAssignment {
6
7 // Event emitted when an assignment is made
8 access(all) event AssignmentMade(username: String, team: String, assignmentIndex: UInt64)
9
10 // Event emitted when all assignments are complete
11 access(all) event AllAssignmentsComplete(assignments: {UInt64: Assignment})
12
13 // Assignment structure
14 access(all) struct Assignment {
15 access(all) let username: String
16 access(all) let team: String
17 access(all) let assignmentIndex: UInt64
18 access(all) let timestamp: UFix64
19
20 init(username: String, team: String, assignmentIndex: UInt64, timestamp: UFix64) {
21 self.username = username
22 self.team = team
23 self.assignmentIndex = assignmentIndex
24 self.timestamp = timestamp
25 }
26 }
27
28 // Storage for all assignments
29 access(all) var assignments: {UInt64: Assignment}
30
31 init() {
32 self.assignments = {}
33 }
34
35 // Main function: Randomly assign all usernames to teams in one transaction
36 // This function uses Flow's revertibleRandom() for on-chain randomness
37 // Combos are passed as arrays of two-team strings like ["Team1, Team2", "Team3, Team4"]
38 access(all) fun assignAllRandomly(usernames: [String], teams: [String], combos: [String]): {UInt64: Assignment} {
39 pre {
40 usernames.length > 0: "Must provide at least one username"
41 (teams.length + combos.length) == usernames.length: "Number of single teams plus combos must equal number of usernames"
42 }
43
44 var remainingUsernames = usernames
45 var remainingSingleTeams = teams
46 var remainingCombos = combos
47 var result: {UInt64: Assignment} = {}
48 var index: UInt64 = 0
49 let currentTime = getCurrentBlock().timestamp
50
51 // Combine single teams and combos into one pool for random assignment
52 var allAssignments: [String] = []
53 var i = 0
54 while i < remainingSingleTeams.length {
55 allAssignments.append(remainingSingleTeams[i])
56 i = i + 1
57 }
58 i = 0
59 while i < remainingCombos.length {
60 allAssignments.append(remainingCombos[i])
61 i = i + 1
62 }
63
64 // Loop through and assign each username to a random team or combo
65 while remainingUsernames.length > 0 {
66 // Get random index for username selection
67 let usernameRandomValue = revertibleRandom<UInt64>()
68 let usernameIndex = usernameRandomValue % UInt64(remainingUsernames.length)
69
70 // Get random index for assignment selection (team or combo)
71 let assignmentRandomValue = revertibleRandom<UInt64>()
72 let assignmentIndex = assignmentRandomValue % UInt64(allAssignments.length)
73
74 // Get the selected username and assignment (team or combo)
75 let selectedUsername = remainingUsernames[Int(usernameIndex)]
76 let selectedAssignment = allAssignments[Int(assignmentIndex)]
77
78 // Create assignment
79 let assignment = Assignment(
80 username: selectedUsername,
81 team: selectedAssignment,
82 assignmentIndex: index,
83 timestamp: currentTime
84 )
85
86 // Store assignment
87 result[index] = assignment
88 self.assignments[index] = assignment
89
90 // Emit event for this assignment
91 emit AssignmentMade(
92 username: selectedUsername,
93 team: selectedAssignment,
94 assignmentIndex: index
95 )
96
97 // Remove assigned username and assignment from remaining pools
98 remainingUsernames = self.removeElement(arr: remainingUsernames, index: Int(usernameIndex))
99 allAssignments = self.removeElement(arr: allAssignments, index: Int(assignmentIndex))
100
101 index = index + 1
102 }
103
104 // Emit completion event
105 emit AllAssignmentsComplete(assignments: result)
106
107 return result
108 }
109
110 // Helper function to remove element from array
111 access(all) fun removeElement(arr: [String], index: Int): [String] {
112 var result: [String] = []
113 var i = 0
114 while i < arr.length {
115 if i != index {
116 result.append(arr[i])
117 }
118 i = i + 1
119 }
120 return result
121 }
122
123 // Get all assignments
124 access(all) fun getAllAssignments(): {UInt64: Assignment} {
125 return self.assignments
126 }
127
128 // Get assignment by index
129 access(all) fun getAssignment(index: UInt64): Assignment? {
130 return self.assignments[index]
131 }
132}
133
134