dossinstitute / sidequest

Apache License 2.0
0 stars 0 forks source link

Point System and Leaderboard #9

Open russlive215 opened 5 months ago

russlive215 commented 5 months ago

Point System and Leaderboard

Description: Enhance the Event Quest contracts by adding a point system for the completion of quests and creating a leaderboard to display users based on their accumulated points.

Acceptance Criteria:

  1. Point System Implementation:
    • Each quest completion should award a specified number of points to the user.
    • Points should be stored and tracked for each user.
  2. Leaderboard Creation:
    • The contract should maintain a leaderboard that ranks users based on their total points.
    • The leaderboard should be retrievable, displaying users in descending order of their points.
    • Provide a function to get the top N users from the leaderboard.
  3. Smart Contract Code:
    • Implement the point system and leaderboard functionalities using Solidity.
    • Ensure points are correctly awarded upon quest completion and that the leaderboard is updated accordingly.
  4. Security and Validations:
    • Validate that points are only awarded once per quest completion.
    • Ensure that the leaderboard is updated atomically with the points award to prevent inconsistencies.

Solidity Code Example:

solidity

Copy code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract EventAmbassadorQuest {
    struct Quest {
        uint256 eventId;
        uint256 startDate;
        uint256 endDate;
        uint256 requiredInteractions;
        uint256 rewardPoints;
        bool isCompleted;
    }

    struct User {
        uint256 points;
        uint256 completedQuests;
        mapping(uint256 => bool) questCompleted;
    }

    address public admin;
    mapping(address => User) public users;
    mapping(uint256 => Quest) public quests;
    address[] public userAddresses;

    event QuestCompleted(address indexed user, uint256 indexed questId, uint256 pointsAwarded);

    modifier onlyAdmin() {
        require(msg.sender == admin, "Only admin can perform this action");
        _;
    }

    constructor() {
        admin = msg.sender;
    }

    function createQuest(
        uint256 questId,
        uint256 eventId,
        uint256 startDate,
        uint256 endDate,
        uint256 requiredInteractions,
        uint256 rewardPoints
    ) external onlyAdmin {
        quests[questId] = Quest(eventId, startDate, endDate, requiredInteractions, rewardPoints, false);
    }

    function registerUser(address user) external onlyAdmin {
        if (users[user].completedQuests == 0) {
            userAddresses.push(user);
        }
    }

    function completeQuest(address user, uint256 questId) external onlyAdmin {
        require(!quests[questId].isCompleted, "Quest already completed");
        require(!users[user].questCompleted[questId], "User already completed this quest");

        users[user].points += quests[questId].rewardPoints;
        users[user].completedQuests += 1;
        users[user].questCompleted[questId] = true;
        quests[questId].isCompleted = true;

        emit QuestCompleted(user, questId, quests[questId].rewardPoints);
    }

    function getLeaderboard(uint256 topN) external view returns (address[] memory, uint256[] memory) {
        require(topN <= userAddresses.length, "Requested topN exceeds number of users");

        address[] memory topUsers = new address[](topN);
        uint256[] memory topPoints = new uint256[](topN);

        for (uint256 i = 0; i < userAddresses.length; i++) {
            for (uint256 j = i + 1; j < userAddresses.length; j++) {
                if (users[userAddresses[j]].points > users[userAddresses[i]].points) {
                    address tempAddress = userAddresses[i];
                    userAddresses[i] = userAddresses[j];
                    userAddresses[j] = tempAddress;
                }
            }
        }

        for (uint256 i = 0; i < topN; i++) {
            topUsers[i] = userAddresses[i];
            topPoints[i] = users[userAddresses[i]].points;
        }

        return (topUsers, topPoints);
    }
}

Testing:

By following this ticket and implementing the provided Solidity code, the Event Ambassador Quest contract will be enhanced with a point system and a leaderboard, providing additional motivation and competitive tracking for users.

4o

wvwatson commented 5 months ago

points: 1, 2, 3, 5, 8, 13, 21

@russlive215 8 @Fr0z0n3 8 @noireconnect2024 13 @wvwatson 8 @tierra-d 21

points: 8