Skip to content

Instantly share code, notes, and snippets.

@taobun
Created July 12, 2019 09:19
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save taobun/2e409e4d11659408508fe893c5cf2fc1 to your computer and use it in GitHub Desktop.
Save taobun/2e409e4d11659408508fe893c5cf2fc1 to your computer and use it in GitHub Desktop.
Optimized sorted List code from Band Protocol' s Solidity102#3 article.
pragma solidity 0.5.9;
contract OptimizedSchool{
mapping(address => uint256) public scores;
mapping(address => address) _nextStudents;
uint256 public listSize;
address constant GUARD = address(1);
constructor() public {
_nextStudents[GUARD] = GUARD;
}
function addStudent(address student, uint256 score, address candidateStudent) public {
require(_nextStudents[student] == address(0));
require(_nextStudents[candidateStudent] != address(0));
require(_verifyIndex(candidateStudent, score, _nextStudents[candidateStudent]));
scores[student] = score;
_nextStudents[student] = _nextStudents[candidateStudent];
_nextStudents[candidateStudent] = student;
listSize++;
}
function increaseScore(
address student,
uint256 score,
address oldCandidateStudent,
address newCandidateStudent
) public {
updateScore(student, scores[student] + score, oldCandidateStudent, newCandidateStudent);
}
function reduceScore(
address student,
uint256 score,
address oldCandidateStudent,
address newCandidateStudent
) public {
updateScore(student, scores[student] - score, oldCandidateStudent, newCandidateStudent);
}
function updateScore(
address student,
uint256 newScore,
address oldCandidateStudent,
address newCandidateStudent
) public {
require(_nextStudents[student] != address(0));
require(_nextStudents[oldCandidateStudent] != address(0));
require(_nextStudents[newCandidateStudent] != address(0));
if(oldCandidateStudent == newCandidateStudent)
{
require(_isPrevStudent(student, oldCandidateStudent));
require(_verifyIndex(newCandidateStudent, newScore, _nextStudents[student]));
scores[student] = newScore;
} else {
removeStudent(student, oldCandidateStudent);
addStudent(student, newScore, newCandidateStudent);
}
}
function removeStudent(address student, address candidateStudent) public {
require(_nextStudents[student] != address(0));
require(_isPrevStudent(student, candidateStudent));
_nextStudents[candidateStudent] = _nextStudents[student];
_nextStudents[student] = address(0);
scores[student] = 0;
listSize--;
}
function getTop(uint256 k) public view returns(address[] memory) {
require(k <= listSize);
address[] memory studentLists = new address[](k);
address currentAddress = _nextStudents[GUARD];
for(uint256 i = 0; i < k; ++i) {
studentLists[i] = currentAddress;
currentAddress = _nextStudents[currentAddress];
}
return studentLists;
}
function _verifyIndex(address prevStudent, uint256 newValue, address nextStudent)
internal
view
returns(bool)
{
return (prevStudent == GUARD || scores[prevStudent] >= newValue) &&
(nextStudent == GUARD || newValue > scores[nextStudent]);
}
function _isPrevStudent(address student, address prevStudent) internal view returns(bool) {
return _nextStudents[prevStudent] == student;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment