uint genesisEvent = 1580540400;
uint[] clockwork;
uint hour;
struct Reg {
bool rank;
uint id;
}
mapping(address => Reg) accountID;
uint[][2] index;
uint[][2] courtUtility;
function incrementCourtUtility() internal {
courtUtility[0].push(index[true].length/2 + index[false].length);
courtUtility[1].push(courtUtility[0].length);
}
bool[3][][] pairData;
function eventScheduler() {
if(clockwork.length == 0) clockwork.length = 24;
uint randomHour = getRandomNumber() % clockwork.length;
if(clockwork[randomHour] == 0) hour = randomHour;
else hour = clockwork[randomHour];
if(clockwork[clockwork.length - 1] == 0) clockwork[randomHour] = clockwork.length - 1;
else clockwork[randomHour] = clockwork[clockwork.length - 1];
clockwork.length--;
}
function assignID(bool _rank) internal {
index[_rank].length++;
accountID[msg.sender].rank = _rank;
accountID[msg.sender].id = index[_rank].length;
}
function shuffle(bool _rank) internal returns (uint id) {
if(index[_rank].length != 0) id = getRandomNumber() % index[_rank].length;
assignID(_rank);
index[_rank][index[_rank].length - 1] = index[_rank][id];
return id;
}
function register() {
index[true][shuffle(true)] = index[true].length;
if(index[true].length%2 == 0) {
incrementCourtUtility();
pairData.length++;
pairData[pairData.length - 1].length = 2;
}
}
function assignCourt(bool _reassign) internal {
uint height = index[true].length/2 - index[false].length % index[true].length/2;
uint id = getRandomNumber() % height;
if(_reassign == false) {
index[false][shuffle(false)] = courtUtility[id];
}
else {
assignID(false);
index[false][index[false].length - 1] = courtUtility[id];
}
delete courtUtility[1][courtUtility[0][id]];
courtUtility[id] = courtUtility[height-1];
courtUtility[1][courtUtility[height-1]] = id;
courtUtility[height-1] = courtUtility[courtUtility.length - 1];
courtUtility[1][courtUtility[courtUtility.length - 1]] = height-1;
courtUtility.length--;
incrementCourtUtility();
}
function immigrate() { assignCourt(false); }
function reassign() { assignCourt(true); }
function getIndex(address _account) internal returns (uint) {
return index[accountID[_account].rank][accountID[_account].id - 1];
}
function getPair(address _account) internal returns (uint) {
if(accountID[_account].rank == true) return (1 + getIndex(_account))/2;
return getIndex(_account) % index[true].length/2;
}
function verification(uint _pairID, address _account, address _signer) internal {
uint signerID = (1+getIndex(_signer))%2;
uint id;
if(accountID[_account].rank == true) {
id = (1 + getIndex(_account))%2;
}
else {
id = 2 + getIndex(_account) / pairData.length;
if(pairData[_pairID].length < id + 1) pairData[_pairID].length = id;
}
pairData[_pairID][id][signerID] = true;
}
function verify(address _account) {
uint pairID = getPair(_account);
require(pairData[pairID].length != 0);
if(pairID == getPair(msg.sender) && accountID[msg.sender].rank == true) verification(pairID, _account, msg.sender);
}
function uploadSignature(address _account, bytes _signature) {
uint pairID = getPair(_account);
require(pairData[pairID].length != 0);
bytes32 sig1;
bytes32 sig2;
assembly {
sig1 := mload(add(_signature,0x20))
sig2 := mload(add(_signature,0x40))
}
bytes32 msgHash = keccak256(_account, eventCounter - 1);
address v1 = ecrecover(msgHash, 27, r, s);
if(pairID == getPair(v1) && accountID[v1].rank == true) verification(pairID, _account, v1);
else {
address v2 = ecrecover(msgHash, 28, r, s);
if(pairID == getPair(v2) && accountID[v2]. rank == true) verification(pairID, _account, v2);
}
}