Last active
November 8, 2018 19:12
-
-
Save resilience-me/d2b17f6ebdd641edad33f34f9e3166d2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// The shuffle algorithm is similar to Algorithm P (Shuffle) from Knuth, 1969, in turn similar to the Fisher–Yates shuffle | |
// from 1938. It gets the position of an object from shufflingIndex, using a random number generator, and then updates the | |
// index so that the same position cannot be given to another object, and does so by switching places between the object | |
// that was picked, and the first object in the list, exchange shufflingIndex[randomNumber] and shufflingIndex[counter]. | |
struct ShuffleAlgorithm { | |
mapping(uint => uint) shufflingIndex; | |
uint counter; | |
} | |
ShuffleAlgorithm shuffleUtility[3]; | |
mapping(address => uint) pseudonymID; | |
mapping(uint => address) pseudonymIndex; | |
mapping(address => uint) immigrantID; | |
mapping(uint => address) immigrantIndex; | |
function sortMe() atTime(State.interlude, State.pseudonymEvent) { | |
require(pseudonymID[msg.sender] == 0); | |
uint8 idx; | |
// Map even and uneven numbers in separate indices, each integer representing a pair with two people | |
// this lets people who opt-in "hitch-hike" on the shuffling of the entire population, so that optIn() | |
// can be invoked continuously | |
if(totalSorted % 2 == 1) { | |
shuffleUtility[0].counter++; | |
idx = 0; | |
} | |
else { | |
shuffleUtility[1].counter++; | |
idx = 1; | |
} | |
uint totalSorted = shuffleUtility[0].counter + shuffleUtility[1].counter; | |
pseudonymID[msg.sender] = totalSorted; | |
pseudonymIndex[totalSorted] = msg.sender; | |
entropy = generateRandomNumber(entropy); | |
uint pos = shuffleUtility[idx].counter; | |
uint randomNumber = 1 + (entropy % pos); | |
shuffleUtility[idx].shufflingIndex[pos] = randomNumber; | |
shuffleUtility[idx].shufflingIndex[randomNumber] = pos; | |
} | |
function getPair(address _nym) view atTime(State.pseudonymEvent, State.endOfPeriod) returns (uint) { | |
uint ID = pseudonymID[_nym]; | |
uint8 idx; | |
uint nominator; | |
if(ID % 2 == 1) { | |
nominator += 1; | |
idx = 0; | |
} | |
else idx = 1; | |
uint pos = nominator / 2; | |
uint pairID = shuffleUtility[idx].shufflingIndex[pos]; | |
return pairID; | |
} | |
function optIn() atTime(State.interlude, State.pseudonymEvent) { | |
uint totalPairs = shuffleUtility[1].counter; | |
shuffleUtility[2].counter++; | |
uint totalImmigrants = shuffleUtility[2].counter; | |
require(totalPairs >= 1); | |
require(totalPairs > (totalImmigrants - 1)); | |
require(immigrantID[msg.sender] == 0); | |
require(borderToken.balanceOf[msg.sender] >= 1); | |
borderToken.balanceOf[msg.sender]--; | |
immigrantID[msg.sender] = totalImmigrants; | |
immigrantIndex[totalImmigrants] = msg.sender; | |
entropy = generateRandomNumber(entropy); | |
uint randomNumber = 1 + (entropy % (totalPairs - totalImmigrants)); | |
uint randomPerson = totalImmigrants + randomNumber; // Mapped to evenNumbers, hitch-hikes on a registered person, and the shuffling on their end | |
// Prune the list with randomPerson, adding the person from the beginning to its position | |
if(shuffleUtility[2].shufflingIndex[randomPerson] == 0) shuffleUtility[2].shufflingIndex[randomPerson] = randomPerson; | |
if(shuffleUtility[2].shufflingIndex[totalImmigrants] == 0) shuffleUtility[2].shufflingIndex[totalImmigrants] = totalImmigrants; | |
shuffleUtility[2].shufflingIndex[randomPerson] = shuffleUtility[2].shufflingIndex[totalImmigrants]; | |
// Assign the person to randomPerson | |
shuffleUtility[2].shufflingIndex[totalImmigrants] = shuffleUtility[2].shufflingIndex[randomPerson]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment