先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。概念設計としてはひとまず終えた。次は、フェデレーションモデル全体の基本設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。そして、それにつながるDApps側である「愛記システム」を、Pythonプログラムで開発していきたい。
愛の行動のPL,BSを決算書として、個人単位、市町村単位、で公表するような愛記システムというものを考えている。愛の行動のデータベースはブロックチェーンのプログラムであり、日々の愛の行動による愛貨の移動を決算書にまとめていきたい。なお、市町村のブロックチェーンのプログラムは以前にも記載している。その市町村のブロックチェーンのプログラムにつながる愛記システムを、DApps側であるPythonプログラムとして設計したい。その場合、基本設計をどのような手順で進めていけばよいか、詳しく見ていこう。
愛記システムを設計するための基本手順を以下に示す。このシステムは、Pythonを用いて市町村のブロックチェーンと連携し、個人および市町村単位での愛の行動のデータを収集、記録し、決算書(PL、BS)として公表するものである。
基本設計のステップ
- 要件定義
- アーキテクチャ設計
- データベース設計
- API設計
- ブロックチェーンインターフェース
- 決算書の生成
- フロントエンド開発
- テストとデプロイ
基本設計の各ステップを順番に進めることで、ブロックチェーンとDAppsとして繋がる「愛記システム」の詳細な設計が可能になる。各ステップでは、関係者との協議やレビューを通じて設計内容を確定していくことが重要である。
1.要件定義
まず、基本設計の最初のステップである要件定義をしていきたい。どのような機能が必要か、どのような問題を解決するのかを洗い出したい。要件定義はシステム設計の最初の重要なステップであり、システムが解決するべき問題と、必要な機能を明確に定義するプロセスである。以下に、愛記システムのプログラムに必要な機能と解決すべき問題を列挙してみよう。
機能要件
-
愛の行動の記録
-
愛貨の移動の記録
-
決算書の生成
-
個人および市町村単位でのデータの集約
-
データのブロックチェーンへの記録と取得
-
愛貨の管理
-
ユーザー管理
-
通知機能
-
レポート機能
-
ダッシュボード
非機能要件
-
セキュリティ
-
可用性
-
パフォーマンス
-
スケーラビリティ
-
ユーザビリティ
-
コンプライアンス
解決すべき問題
-
透明性と信頼性の確保
-
データの一元管理
-
愛の行動の促進
-
評価制度の確立
-
データのセキュリティとプライバシーの保護
これらの要件を基に、愛記システムの基本設計を進めていくことが重要である。次のステップでは、これらの要件を具体的なアーキテクチャ設計に反映していくことになる。まずは、要件定義の解決すべき問題を一つずつクリアにしていきたい。
評価制度の確立
愛の行動の評価は、以下のような基準とプロセスに基づいて行われる。これにより、ユーザーの行動を評価し、フィードバックを提供する。
○個人の評価基準:
基本評価基準
- 波動レベルの偏り:波動レベルが偏らないこと。
- 愛の行動量:月に30回以上の愛の行動を行うこと。
- 次元の偏り:行動が特定の次元に偏らないこと。
- 対象相手:行動の対象が特定の相手に偏らないこと。
- ゆらぎ件数:月に3件以上のゆらぎを達成すること。
応用評価基準
- 現波動レベル:各次元毎の各生命体での各レベルの行動を集計すること。
- 現次元レベル:各次元毎の各生命体での行動を集計すること。
- 目標到達度:申告した目標に対しての到達度を集計すること。
- 役割経験数:役割の経験を集計すること。
- 現役割等級:各次元毎の各生命体での役割の貢献度を集計すること。
評価プロセス
-
データ収集
- 各ユーザーの愛の行動データを月次で収集する。
- 行動の日時、対象相手、次元、波動レベル、愛の行動量などのデータを記録する。
-
コンピテンシーモデルの設定
- 標準行動モデルを設定し、これに基づいて評価基準を設ける。
- 時間の経過とともに基準を見直し、更新する。
-
データ分析
- 収集されたデータをもとに、各ユーザーの行動を評価する。
- 偏りの分析には、標準偏差などの統計的手法を用いる。
-
フィードバックの提供
- 評価結果をユーザーにフィードバックする。
- グラフやレポート形式で視覚的に表示し、自己理解を促進する。
目標到達度の評価
次は、目標到達度:申告した目標に対しての到達度を集計すること、を測定したい。なお、単純に目標達成度を測るだけでは難しい。なぜなら、相手から愛貨をもらうことも多々あるからだ。そこを十分考慮せねばならない。
まず、愛貨を市町村に最初に申告して愛貨を付与されたところからスタートする。相手に愛の行動をしたら愛貨を減らせるし、相手からされたら愛貨は増える。何とか、愛貨を減らし、ゼロにちかづけるのだが、相手からされることも多々あるので愛貨をもらう場面も多々あり、ゼロにはならないだろう。そこで、目標達成度として、申告に対してどれだけ減らせられたか、さらには相手からもらった分で増えた分がどれだけで、それをどれだけさらに減らせたか、というのを評価するような設計にしたい。結局、自己申告時よりも愛貨が増えることもありえるし、それでも愛の行動をたくさんしている人もいる。そのあたりをどのように評価設計するのかがポイントになる。
評価要素:
- 減少率 (Reduction Rate): 初期申告額に対する減少額の割合。
- 増加率 (Re-Reduction Rate): 受取額に対する再減少額の割合。
- 行動頻度 (Action Frequency): 行動の総回数。
- 愛貨の純減少額 (Net Reduction Amount): 初期申告額に対する最終的な愛貨の減少額(受け取った愛貨を考慮して)。
- 愛貨の再受け取り数 (Re-received Count): 受け取った愛貨をさらに再利用した回数。
評価式: Overall Achievement = α×Reduction Rate+β×Re-Reduction Rate+γ×Action Frequency+δ×Net Reduction Amount+ϵ×Re-received Count
※ここで、α,β,γ,δ,ϵ は各要素に対する重みである。これにより、愛の行動の多様性と頻度をバランス良く評価できる。
・プログラムの実装
○スマートコントラクト (Rust):
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::string::String;
use ink_lang as ink;
use ink_storage::collections::HashMap as StorageHashMap;
#[ink::contract]
mod love_currency {
use super::*;
#[ink(storage)]
pub struct LoveCurrency {
initial_declaration: StorageHashMap<AccountId, u64>,
reduction_amount: StorageHashMap<AccountId, u64>,
received_amount: StorageHashMap<AccountId, u64>,
re_reduction_amount: StorageHashMap<AccountId, u64>,
action_count: StorageHashMap<AccountId, u64>,
re_received_count: StorageHashMap<AccountId, u64>,
}
impl LoveCurrency {
#[ink(constructor)]
pub fn new() -> Self {
Self {
initial_declaration: StorageHashMap::new(),
reduction_amount: StorageHashMap::new(),
received_amount: StorageHashMap::new(),
re_reduction_amount: StorageHashMap::new(),
action_count: StorageHashMap::new(),
re_received_count: StorageHashMap::new(),
}
}
#[ink(message)]
pub fn declare_initial(&mut self, amount: u64) {
let caller = self.env().caller();
self.initial_declaration.insert(caller, amount);
}
#[ink(message)]
pub fn record_action(&mut self, amount: u64) {
let caller = self.env().caller();
let reduction = self.reduction_amount.entry(caller).or_insert(0);
*reduction += amount;
let action = self.action_count.entry(caller).or_insert(0);
*action += 1;
}
#[ink(message)]
pub fn receive_love(&mut self, amount: u64) {
let caller = self.env().caller();
let received = self.received_amount.entry(caller).or_insert(0);
*received += amount;
}
#[ink(message)]
pub fn re_reduce_love(&mut self, amount: u64) {
let caller = self.env().caller();
let re_reduction = self.re_reduction_amount.entry(caller).or_insert(0);
*re_reduction += amount;
let re_received = self.re_received_count.entry(caller).or_insert(0);
*re_received += 1;
}
#[ink(message)]
pub fn get_achievement(&self, user: AccountId) -> (u64, u64, u64, u64, u64, u64) {
(
*self.initial_declaration.get(&user).unwrap_or(&0),
*self.reduction_amount.get(&user).unwrap_or(&0),
*self.received_amount.get(&user).unwrap_or(&0),
*self.re_reduction_amount.get(&user).unwrap_or(&0),
*self.action_count.get(&user).unwrap_or(&0),
*self.re_received_count.get(&user).unwrap_or(&0),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[ink::test]
fn test_declare_initial() {
let mut contract = LoveCurrency::new();
contract.declare_initial(1000);
let caller = ink_env::test::default_accounts::<ink_env::DefaultEnvironment>().alice;
assert_eq!(contract.get_achievement(caller).0, 1000);
}
#[ink::test]
fn test_record_action() {
let mut contract = LoveCurrency::new();
contract.record_action(500);
let caller = ink_env::test::default_accounts::<ink_env::DefaultEnvironment>().alice;
assert_eq!(contract.get_achievement(caller).1, 500);
assert_eq!(contract.get_achievement(caller).4, 1);
}
#[ink::test]
fn test_receive_love() {
let mut contract = LoveCurrency::new();
contract.receive_love(200);
let caller = ink_env::test::default_accounts::<ink_env::DefaultEnvironment>().alice;
assert_eq!(contract.get_achievement(caller).2, 200);
}
#[ink::test]
fn test_re_reduce_love() {
let mut contract = LoveCurrency::new();
contract.re_reduce_love(100);
let caller = ink_env::test::default_accounts::<ink_env::DefaultEnvironment>().alice;
assert_eq!(contract.get_achievement(caller).3, 100);
assert_eq!(contract.get_achievement(caller).5, 1);
}
}
}
○DApps側のPythonプログラム:
from flask import Flask, request, jsonify
from web3 import Web3
app = Flask(__name__)
# Web3の初期化
web3 = Web3(Web3.HTTPProvider('http://localhost:8545'))
contract_address = '0xYourContractAddress'
contract_abi = [...] # スマートコントラクトのABI
contract = web3.eth.contract(address=contract_address, abi=contract_abi)
# 各要素の重み
ALPHA = 0.3
BETA = 0.2
GAMMA = 0.2
DELTA = 0.2
EPSILON = 0.1
@app.route('/declare_initial', methods=['POST'])
def declare_initial():
data = request.get_json()
user_address = data['user_address']
amount = data['amount']
try:
tx_hash = contract.functions.declare_initial(amount).transact({'from': user_address})
web3.eth.wait_for_transaction_receipt(tx_hash)
return jsonify({"message": "Initial declaration recorded successfully"}), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/record_action', methods=['POST'])
def record_action():
data = request.get_json()
user_address = data['user_address']
amount = data['amount']
try:
tx_hash = contract.functions.record_action(amount).transact({'from': user_address})
web3.eth.wait_for_transaction_receipt(tx_hash)
return jsonify({"message": "Action recorded successfully"}), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/receive_love', methods=['POST'])
def receive_love():
data = request.get_json()
user_address = data['user_address']
amount = data['amount']
try:
tx_hash = contract.functions.receive_love(amount).transact({'from': user_address})
web3.eth.wait_for_transaction_receipt(tx_hash)
return jsonify({"message": "Love received successfully"}), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/re_reduce_love', methods=['POST'])
def re_reduce_love():
data = request.get_json()
user_address = data['user_address']
amount = data['amount']
try:
tx_hash = contract.functions.re_reduce_love(amount).transact({'from': user_address})
web3.eth.wait_for_transaction_receipt(tx_hash)
return jsonify({"message": "Love re-reduced successfully"}), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
@app.route('/get_achievement', methods=['GET'])
def get_achievement():
user_address = request.args.get('user_address')
try:
achievement = contract.functions.get_achievement(user_address).call()
initial_declaration, reduction_amount, received_amount, re_reduction_amount, action_count, re_received_count = achievement
reduction_rate = reduction_amount / initial_declaration if initial_declaration != 0 else 0
re_reduction_rate = re_reduction_amount / received_amount if received_amount != 0 else 0
net_reduction_amount = initial_declaration - reduction_amount + re_reduction_amount
overall_achievement = (
ALPHA * reduction_rate +
BETA * re_reduction_rate +
GAMMA * action_count +
DELTA * net_reduction_amount +
EPSILON * re_received_count
)
return jsonify({
"initial_declaration": initial_declaration,
"reduction_amount": reduction_amount,
"received_amount": received_amount,
"re_reduction_amount": re_reduction_amount,
"action_count": action_count,
"re_received_count": re_received_count,
"reduction_rate": reduction_rate,
"re_reduction_rate": re_reduction_rate,
"net_reduction_amount": net_reduction_amount,
"overall_achievement": overall_achievement
}), 200
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)
・説明
-
スマートコントラクト (Rust):
- 初期申告、行動、愛の受け取り、再減少を記録。
- get_achievement 関数でユーザーの達成度データを取得。
-
DApps側 (Python):
- ユーザーの行動を記録し、目標達成度を評価。
- 各要素に重みを付けて総合評価を計算。
この設計により、ユーザーが申告した目標に対する到達度を詳細に評価することができる。評価要素ごとに重みを設定し、ユーザーの行動頻度や愛貨の減少・増加を総合的に評価する。
いかがであろうか、これで目標到達度を表示させる仕組みができた。これで自分の目標到達度を知ることができる。参考値ではあるが、自分の目標到達度を知ることができれば、自分の行動をどのように変えていけばいいのかとか、もっと到達度を上げたいとか、欲求が芽生え、さらなる愛の行動をしていくことができるのであろう。