Skip to content

Commit

Permalink
add completed example contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
neila committed Jan 22, 2024
1 parent 847c566 commit 26adef2
Show file tree
Hide file tree
Showing 3 changed files with 446 additions and 0 deletions.
140 changes: 140 additions & 0 deletions contracts/Government.sol
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;
}
}
190 changes: 190 additions & 0 deletions contracts/Medical.sol
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;
}
}
Loading

0 comments on commit 26adef2

Please sign in to comment.