الدرس رقم 3

票數統計與結果公布

在本章中,我們將實現去中心化投票繫統的最後兩個部分:票數統計與結果公布。我們將對Voter合約進行最後的擴展,併創建用於計算穫勝提案的函數。

擴展Voter合約

首先,我們在合約中添加winningProposal函數。此函數將遍歷所有提案併返回票數最多的提案。此外,我們將創建一個winnerName函數,用於返回穫勝提案的名稱。合約的最終版本如下:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Voter {
    struct Person {
        bool voted;  
        uint vote;   
    }

    struct Proposal {
        string name;   
        uint voteCount; 
    }

    Proposal[] public proposals;
    mapping(address => Person) public voters;

    function registerVoter() public {
        voters[msg.sender].voted = false;
    }

    function addProposal(string memory _name) public {
        proposals.push(Proposal(_name, 0));
    }

    function vote(uint _proposal) public { 
     require(_proposal < proposals.length, "Invalid proposal index."); // This is the added check 

     Person storage sender = voters[msg.sender]; 
     require(!sender.voted, "Already voted."); 
     sender.voted = true; 
     sender.vote = _proposal; 

     proposals[_proposal].voteCount += 1; 
    }

    function winningProposal() public view returns (uint winningProposal_) {
        uint winningVoteCount = 0;
        for (uint p = 0; p < proposals.length; p++) {
            if (proposals[p].voteCount > winningVoteCount) {
                winningVoteCount = proposals[p].voteCount;
                winningProposal_ = p;
            }
        }
    }

    function winnerName() public view returns (string memory winnerName_) {
        winnerName_ = proposals[winningProposal()].name;
    }
}

代碼解析

我們來解釋一下新添加的兩個函數:

  1. Winning Proposal函數:此函數將遍歷所有提案併找到投票數最高的那個。它返回該提案在proposals數組中的索引。此函數是一個view函數,隻讀取數據,不修改合約狀態。

  2. Winner Name函數:此函數會調用winningProposal函數穫取穫勝提案的索引,然後返回穫勝提案的名稱。

編譯和測試

單擊左側邊欄上的Solidity編譯器圖標,然後單擊“Compile”按鈕,來編譯您的合約。

在“Deploy & Run Transactions”選項卡中部署併運行合約。註冊投票人,添加提案,進行投票,最後查看穫勝者。

操作步驟:

  1. 部署:首先,單擊Solidity編譯器圖標下方的”Deploy & Run Transactions”圖標,使用”JavaScript VM”環境,然後單擊”Deploy”。
  2. 註冊投票人:合約部署完成後,會在”Deployed Contracts”版塊顯示。單擊箭頭展開內容,我們合約的所有函數將在這裡顯示。
  3. 要註冊投票人,請使用registerVoter函數。由於我們已經事先將合約編程爲:將調用此函數的帳戶註冊爲投票人,您可以在”Deploy & Run Transactions”選項卡的”Account”下拉列錶中切換帳戶。選擇帳戶後,點擊registerVoter函數。對要註冊爲投票人的每個帳戶重覆此步驟。
  4. 添加提案:要添加提案,請使用addProposal函數。在函數旁邊的輸入框中輸入提案名稱,然後單擊該函數。對要添加的每個提案重覆此步驟。
  5. 投票:要進行投票,請切換到投票人帳戶併找到vote 函數。在函數旁邊的輸入框中輸入您要投票的提案的索引(即您添加它的順序,從0開始),然後點擊該函數。爲每個投票人重覆此步驟。
  6. 查看穫勝者:所有投票人投票完成後,即可查看穫勝者。找到winnerName 函數併點擊,屏幕下方控製颱中將顯示穫勝提案的名稱。
  7. 請記住,區塊鏈中的所有操作(包括Remix中的測試操作)都屬於交易。您可以在控製颱中展開交易詳情,查看更多信息,如交易成本和數據,有助於您更好地了解您的合約如何與區塊鏈交互。

在下一章中,我們將探討合約交互與事件記録。我們將學習不衕的合約如何交互,以及如何在區塊鏈上記録和監控活動。恭喜大家在以太坊上構建了自己的第一個去中心化投票繫統!

إخلاء المسؤولية
* ينطوي الاستثمار في العملات الرقمية على مخاطر كبيرة. فيرجى المتابعة بحذر. ولا تهدف الدورة التدريبية إلى تقديم المشورة الاستثمارية.
* تم إنشاء الدورة التدريبية من قبل المؤلف الذي انضم إلى مركز التعلّم في Gate. ويُرجى العلم أنّ أي رأي يشاركه المؤلف لا يمثّل مركز التعلّم في Gate.
الكتالوج
الدرس رقم 3

票數統計與結果公布

在本章中,我們將實現去中心化投票繫統的最後兩個部分:票數統計與結果公布。我們將對Voter合約進行最後的擴展,併創建用於計算穫勝提案的函數。

擴展Voter合約

首先,我們在合約中添加winningProposal函數。此函數將遍歷所有提案併返回票數最多的提案。此外,我們將創建一個winnerName函數,用於返回穫勝提案的名稱。合約的最終版本如下:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Voter {
    struct Person {
        bool voted;  
        uint vote;   
    }

    struct Proposal {
        string name;   
        uint voteCount; 
    }

    Proposal[] public proposals;
    mapping(address => Person) public voters;

    function registerVoter() public {
        voters[msg.sender].voted = false;
    }

    function addProposal(string memory _name) public {
        proposals.push(Proposal(_name, 0));
    }

    function vote(uint _proposal) public { 
     require(_proposal < proposals.length, "Invalid proposal index."); // This is the added check 

     Person storage sender = voters[msg.sender]; 
     require(!sender.voted, "Already voted."); 
     sender.voted = true; 
     sender.vote = _proposal; 

     proposals[_proposal].voteCount += 1; 
    }

    function winningProposal() public view returns (uint winningProposal_) {
        uint winningVoteCount = 0;
        for (uint p = 0; p < proposals.length; p++) {
            if (proposals[p].voteCount > winningVoteCount) {
                winningVoteCount = proposals[p].voteCount;
                winningProposal_ = p;
            }
        }
    }

    function winnerName() public view returns (string memory winnerName_) {
        winnerName_ = proposals[winningProposal()].name;
    }
}

代碼解析

我們來解釋一下新添加的兩個函數:

  1. Winning Proposal函數:此函數將遍歷所有提案併找到投票數最高的那個。它返回該提案在proposals數組中的索引。此函數是一個view函數,隻讀取數據,不修改合約狀態。

  2. Winner Name函數:此函數會調用winningProposal函數穫取穫勝提案的索引,然後返回穫勝提案的名稱。

編譯和測試

單擊左側邊欄上的Solidity編譯器圖標,然後單擊“Compile”按鈕,來編譯您的合約。

在“Deploy & Run Transactions”選項卡中部署併運行合約。註冊投票人,添加提案,進行投票,最後查看穫勝者。

操作步驟:

  1. 部署:首先,單擊Solidity編譯器圖標下方的”Deploy & Run Transactions”圖標,使用”JavaScript VM”環境,然後單擊”Deploy”。
  2. 註冊投票人:合約部署完成後,會在”Deployed Contracts”版塊顯示。單擊箭頭展開內容,我們合約的所有函數將在這裡顯示。
  3. 要註冊投票人,請使用registerVoter函數。由於我們已經事先將合約編程爲:將調用此函數的帳戶註冊爲投票人,您可以在”Deploy & Run Transactions”選項卡的”Account”下拉列錶中切換帳戶。選擇帳戶後,點擊registerVoter函數。對要註冊爲投票人的每個帳戶重覆此步驟。
  4. 添加提案:要添加提案,請使用addProposal函數。在函數旁邊的輸入框中輸入提案名稱,然後單擊該函數。對要添加的每個提案重覆此步驟。
  5. 投票:要進行投票,請切換到投票人帳戶併找到vote 函數。在函數旁邊的輸入框中輸入您要投票的提案的索引(即您添加它的順序,從0開始),然後點擊該函數。爲每個投票人重覆此步驟。
  6. 查看穫勝者:所有投票人投票完成後,即可查看穫勝者。找到winnerName 函數併點擊,屏幕下方控製颱中將顯示穫勝提案的名稱。
  7. 請記住,區塊鏈中的所有操作(包括Remix中的測試操作)都屬於交易。您可以在控製颱中展開交易詳情,查看更多信息,如交易成本和數據,有助於您更好地了解您的合約如何與區塊鏈交互。

在下一章中,我們將探討合約交互與事件記録。我們將學習不衕的合約如何交互,以及如何在區塊鏈上記録和監控活動。恭喜大家在以太坊上構建了自己的第一個去中心化投票繫統!

إخلاء المسؤولية
* ينطوي الاستثمار في العملات الرقمية على مخاطر كبيرة. فيرجى المتابعة بحذر. ولا تهدف الدورة التدريبية إلى تقديم المشورة الاستثمارية.
* تم إنشاء الدورة التدريبية من قبل المؤلف الذي انضم إلى مركز التعلّم في Gate. ويُرجى العلم أنّ أي رأي يشاركه المؤلف لا يمثّل مركز التعلّم في Gate.