-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
446 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.17; | ||
|
||
import "hardhat/console.sol"; | ||
import "./interfaces/IGovernment.sol"; | ||
|
||
contract Government is IGovernment { | ||
// イベント定義 | ||
event NewCandidate( | ||
address candidate, | ||
uint256 timestamp, | ||
uint256 numOfVotes | ||
); | ||
event NewVote(address voter, address candidate); | ||
|
||
// 立候補情報の構造体定義 | ||
struct Candidate { | ||
address candidate; // 立候補者のウォレットアドレス | ||
uint256 timestamp; // 立候補した瞬間のタイムスタンプ | ||
uint256 numOfVotes; // 得票数 | ||
} | ||
|
||
Candidate[] private _candidates; | ||
|
||
// 二重立候補の防止 | ||
mapping(address => bool) public isCandidate; | ||
|
||
// 二重投票の防止 | ||
mapping(address => bool) public isVoter; | ||
|
||
constructor() { | ||
console.log("This is SmartGovernment contract!"); | ||
} | ||
|
||
function runForCandidate() external { | ||
// 既に立候補済みかどうかを確認 | ||
require(isCandidate[msg.sender] != true, "You already run for!"); | ||
if (startTimeStamp == 0) { | ||
startTimeStamp = block.timestamp; | ||
endTimeStamp = startTimeStamp + 2 weeks; | ||
} | ||
// 選挙終了時刻以降に立候補の関数を呼び出した場合はエラー処理 | ||
if (startTimeStamp != 0) { | ||
require( | ||
endTimeStamp > block.timestamp, | ||
"You are too late to run for!" | ||
); | ||
} | ||
// 立候補フラグを建てる | ||
isCandidate[msg.sender] = true; | ||
// 配列に立候補情報を格納 | ||
_candidates.push(Candidate(msg.sender, block.timestamp, 0)); | ||
// フロントエンド側に新たな立候補情報を通知 | ||
emit NewCandidate(msg.sender, block.timestamp, 0); | ||
} | ||
|
||
// 立候補の内容をすべて取得する関数 | ||
function getAllCandidates() public view returns (Candidate[] memory) { | ||
return _candidates; | ||
} | ||
|
||
// 開始時間の取得 | ||
uint256 public startTimeStamp; | ||
|
||
// 終了時間の取得 | ||
uint256 public endTimeStamp; | ||
|
||
function vote(address _candidateAddress) external { | ||
uint256 candidateid; | ||
for (uint256 index = 0; index < _candidates.length; index++) { | ||
if (_candidateAddress == _candidates[index].candidate) { | ||
candidateid = index; | ||
} | ||
} | ||
// 立候補者は投票できないよう制限 | ||
require(isCandidate[msg.sender] != true, "Candidates can't vote!"); | ||
// 既に投票もしくは棄権した場合は投票できないよう制限 | ||
require(isVoter[msg.sender] != true, "You already vote or abstain!"); | ||
if (startTimeStamp != 0) { | ||
require( | ||
endTimeStamp > block.timestamp, | ||
"You are too late to vote!" | ||
); | ||
} | ||
// 投票者・棄権者フラグを建てる | ||
isVoter[msg.sender] = true; | ||
// 投票された立候補者の得票数を1増やす | ||
_candidates[candidateid].numOfVotes += 1; | ||
// フロントエンド側に新たな投票情報を通知 | ||
emit NewVote(msg.sender, _candidates[candidateid].candidate); | ||
} | ||
|
||
// 棄権する関数 | ||
function abstain() external { | ||
// 既に投票もしくは棄権した場合は棄権できないよう制限 | ||
require(isVoter[msg.sender] != true, "You already vote or abstain!"); | ||
if (startTimeStamp != 0) { | ||
require( | ||
endTimeStamp > block.timestamp, | ||
"You are too late to vote!" | ||
); | ||
} | ||
isVoter[msg.sender] = true; | ||
} | ||
|
||
address private _winner; | ||
|
||
// 新会長を選出する関数 | ||
function determinePresident() external { | ||
require(endTimeStamp <= block.timestamp, "not yet timestamp!"); | ||
uint256 chairmanIndex; | ||
// 全立候補者のうち、最も得票数の多い立候補者のNoを探索 | ||
require(_candidates.length > 0, "There are no _candidates yet"); | ||
for (uint256 i; i < _candidates.length - 1; i++) { | ||
(_candidates[chairmanIndex].numOfVotes > | ||
_candidates[i + 1].numOfVotes | ||
? chairmanIndex = i | ||
: chairmanIndex = i + 1); | ||
} | ||
_winner = _candidates[chairmanIndex].candidate; | ||
} | ||
|
||
function getPresident() external view returns (address) { | ||
return _winner; | ||
} | ||
|
||
function numberOfVotes(address _candidateAddress) | ||
external | ||
view | ||
returns (uint256) | ||
{ | ||
for (uint256 i = 0; i < _candidates.length; i++) { | ||
if (_candidates[i].candidate == _candidateAddress) { | ||
return _candidates[i].numOfVotes; | ||
} | ||
} | ||
return 0; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.17; | ||
import "hardhat/console.sol"; | ||
import "./interfaces/IMedical.sol"; | ||
|
||
contract Medical is IMedical { | ||
//受診者データの構造体を作成 | ||
struct Patient { | ||
address ownerAddress; //構造体の作成者(本人であることを判定する) | ||
string name; //名前 | ||
string bloodType; //血液型 | ||
uint256 lastUpdate; //最終更新日 | ||
address doctorAddress; //担当医師のアドレス | ||
uint256 id; //ID | ||
} | ||
|
||
//医師データの構造体を作成 | ||
struct Doctor { | ||
address ownerAddress; //構造体の作成者(本人であることを判定する) | ||
string name; //名前 | ||
uint256 id; //ID | ||
} | ||
|
||
uint256 private _patientId = 1; //受診者のID | ||
uint256 private _doctorId = 1; //医師のID | ||
|
||
Patient[] public patients; | ||
Doctor[] public doctors; | ||
|
||
mapping(address => uint256) private _patientAddressToId; //受診者のオーナーアドレスからIDをマッピング | ||
mapping(uint256 => address) private _idToDoctorAddress; //IDから医師のアドレスをマッピング | ||
mapping(address => uint256) private _doctorAddressToId; //医師のオーナーアドレスからIDをマッピング | ||
mapping(address => string) private _doctorAddressToName; //医師のオーナーアドレスから名前をマッピング | ||
|
||
function register(string memory _name, string memory _bloodType) external { | ||
require(_patientAddressToId[msg.sender] == 0, "already exist."); //未作成時のみ実行可能 | ||
address _initialAddress; //医師の初期値アドレス | ||
Patient memory _newPatient = Patient( | ||
msg.sender, | ||
_name, | ||
_bloodType, | ||
block.timestamp, | ||
_initialAddress, | ||
_patientId | ||
); | ||
patients.push(_newPatient); | ||
_patientAddressToId[msg.sender] = _patientId; | ||
_patientId++; | ||
} | ||
|
||
function updateName(string memory _name) external { | ||
require(_patientAddressToId[msg.sender] > 0, "not registered yet"); | ||
uint256 _ownerId = _patientAddressToId[msg.sender] - 1; | ||
patients[_ownerId].name = _name; | ||
patients[_ownerId].lastUpdate = block.timestamp; | ||
} | ||
|
||
function updateBloodType(string memory _bloodType) external { | ||
require(_patientAddressToId[msg.sender] > 0, "not registered yet"); | ||
uint256 _ownerId = _patientAddressToId[msg.sender] - 1; | ||
patients[_ownerId].bloodType = _bloodType; | ||
patients[_ownerId].lastUpdate = block.timestamp; | ||
} | ||
|
||
// 医師の登録も実装されている | ||
function updateDoctorInfo(address _doctorAddress, string memory _name) | ||
external | ||
{ | ||
require(_doctorAddressToId[_doctorAddress] == 0, "already exist."); //未作成時のみ実行可能 | ||
Doctor memory _newDoctor = Doctor(_doctorAddress, _name, _doctorId); | ||
doctors.push(_newDoctor); | ||
_doctorAddressToId[_doctorAddress] = _doctorId; | ||
_doctorId++; | ||
_doctorAddressToName[_doctorAddress] = _name; //医師の名前をマッピングで登録 | ||
} | ||
|
||
function getMedicalData(address _patientAddress) | ||
external | ||
view | ||
returns ( | ||
string memory name, | ||
string memory bloodType, | ||
uint256 lastUpdatedtime | ||
) | ||
{ | ||
require(_patientAddressToId[_patientAddress] > 0, "not registered yet"); | ||
uint256 _ownerId = _patientAddressToId[_patientAddress] - 1; | ||
require( | ||
patients[_ownerId].doctorAddress == msg.sender || | ||
patients[_ownerId].ownerAddress == msg.sender, | ||
"not owner or doctor" | ||
); | ||
return ( | ||
patients[_ownerId].name, | ||
patients[_ownerId].bloodType, | ||
patients[_ownerId].lastUpdate | ||
); | ||
} | ||
|
||
function provideViewingAccess(address _doctorAddress) external { | ||
require(_patientAddressToId[msg.sender] > 0, "not registered yet"); | ||
uint256 _ownerId = _patientAddressToId[msg.sender] - 1; | ||
patients[_ownerId].doctorAddress = _doctorAddress; | ||
_idToDoctorAddress[_ownerId] = _doctorAddress; | ||
} | ||
|
||
function isViewingAccessGranted( | ||
address _patientAddress, | ||
address _medicalProviderAddress | ||
) external view returns (bool) { | ||
uint256 _ownerId = _patientAddressToId[_patientAddress] - 1; | ||
return patients[_ownerId].doctorAddress == _medicalProviderAddress; | ||
} | ||
|
||
//受診者が自分の情報を確認するための関数。 | ||
function viewPatientProfile() | ||
external | ||
view | ||
returns ( | ||
string memory, | ||
string memory, | ||
uint256, | ||
address, | ||
string memory | ||
) | ||
{ | ||
require(_patientAddressToId[msg.sender] > 0, "not registered yet"); | ||
uint256 _ownerId = _patientAddressToId[msg.sender] - 1; | ||
address _doctorAddress = patients[_ownerId].doctorAddress; | ||
string memory _doctorName = _doctorAddressToName[_doctorAddress]; //医師の名前をマッピングから取得 | ||
return ( | ||
patients[_ownerId].name, | ||
patients[_ownerId].bloodType, | ||
patients[_ownerId].lastUpdate, | ||
patients[_ownerId].ownerAddress, | ||
_doctorName | ||
); | ||
} | ||
|
||
//医師が自分の情報を確認するための関数。 | ||
function viewDoctorProfile() | ||
external | ||
view | ||
returns ( | ||
string memory, | ||
uint256, | ||
address | ||
) | ||
{ | ||
require(_doctorAddressToId[msg.sender] > 0, " not registered yet"); | ||
uint256 _ownerId = _doctorAddressToId[msg.sender] - 1; | ||
return ( | ||
doctors[_ownerId].name, | ||
_ownerId, | ||
doctors[_ownerId].ownerAddress | ||
); | ||
} | ||
|
||
//受診者が医師を削除するための関数。 | ||
function deleteDoctor() external { | ||
require(_patientAddressToId[msg.sender] > 0, "Y not registered yet"); | ||
uint256 _ownerId = _patientAddressToId[msg.sender] - 1; | ||
address _initialAddress; //医師の初期値アドレス | ||
patients[_ownerId].doctorAddress = _initialAddress; | ||
_idToDoctorAddress[_ownerId] = _initialAddress; | ||
} | ||
|
||
//医師に紐づく受診者を取得 | ||
function viewClientsList() external view returns (Patient[] memory) { | ||
uint256 count = 0; | ||
for (uint256 i = 0; i < patients.length; i++) { | ||
if (_idToDoctorAddress[i] == msg.sender) { | ||
count++; | ||
} | ||
} | ||
Patient[] memory result = new Patient[](count); | ||
for (uint256 i = 0; i < patients.length; i++) { | ||
if (_idToDoctorAddress[i] == msg.sender) { | ||
result[i] = patients[i]; | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
//医師全員を取得 | ||
function viewAllDoctors() external view returns (Doctor[] memory) { | ||
return doctors; | ||
} | ||
} |
Oops, something went wrong.