愛記システムの基本設計:DApps側である愛記システム 評価制度の確立 現次元レベル | 続・ティール組織 研究会のブログ

続・ティール組織 研究会のブログ

ティール組織が話題になっているが、具現化するにはどうしたらよいか?
その研究を続けるにあたり、さらに次の形態である、続・ティール組織なるものまで視野に入れ、具体的な施策・行動内容を研究・支援する会。

先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。概念設計としてはひとまず終えた。次は、フェデレーションモデル全体の基本設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。そして、それにつながるDApps側である「愛記システム」を、Pythonプログラムで開発していきたい。

 

愛の行動のPL,BSを決算書として、個人単位、市町村単位、で公表するような愛記システムというものを考えている。愛の行動のデータベースはブロックチェーンのプログラムであり、日々の愛の行動による愛貨の移動を決算書にまとめていきたい。なお、市町村のブロックチェーンのプログラムは以前にも記載している。その市町村のブロックチェーンのプログラムにつながる愛記システムを、DApps側であるPythonプログラムとして設計したい。その場合、基本設計をどのような手順で進めていけばよいか、詳しく見ていこう。

 

愛記システムを設計するための基本手順を以下に示す。このシステムは、Pythonを用いて市町村のブロックチェーンと連携し、個人および市町村単位での愛の行動のデータを収集、記録し、決算書(PL、BS)として公表するものである。

基本設計のステップ

  1. 要件定義
  2. アーキテクチャ設計
  3. データベース設計
  4. API設計
  5. ブロックチェーンインターフェース
  6. 決算書の生成
  7. フロントエンド開発
  8. テストとデプロイ

基本設計の各ステップを順番に進めることで、ブロックチェーンとDAppsとして繋がる「愛記システム」の詳細な設計が可能になる。各ステップでは、関係者との協議やレビューを通じて設計内容を確定していくことが重要である。

1.要件定義

まず、基本設計の最初のステップである要件定義をしていきたい。どのような機能が必要か、どのような問題を解決するのかを洗い出したい。要件定義はシステム設計の最初の重要なステップであり、システムが解決するべき問題と、必要な機能を明確に定義するプロセスである。以下に、愛記システムのプログラムに必要な機能と解決すべき問題を列挙してみよう。

機能要件

  1. 愛の行動の記録

  2. 愛貨の移動の記録

  3. 決算書の生成

  4. 個人および市町村単位でのデータの集約

  5. データのブロックチェーンへの記録と取得

  6. 愛貨の管理

  7. ユーザー管理

  8. 通知機能

  9. レポート機能

  10. ダッシュボード

非機能要件

  1. セキュリティ

  2. 可用性

  3. パフォーマンス

  4. スケーラビリティ

  5. ユーザビリティ

  6. コンプライアンス

解決すべき問題

  1. 透明性と信頼性の確保

  2. データの一元管理

  3. 愛の行動の促進

  4. 評価制度の確立

  5. データのセキュリティとプライバシーの保護

これらの要件を基に、愛記システムの基本設計を進めていくことが重要である。次のステップでは、これらの要件を具体的なアーキテクチャ設計に反映していくことになる。まずは、要件定義の解決すべき問題を一つずつクリアにしていきたい。

評価制度の確立

愛の行動の評価は、以下のような基準とプロセスに基づいて行われる。これにより、ユーザーの行動を評価し、フィードバックを提供する。

○個人の評価基準:

基本評価基準

  • 波動レベルの偏り:波動レベルが偏らないこと。
  • 愛の行動量:月に30回以上の愛の行動を行うこと。
  • 次元の偏り:行動が特定の次元に偏らないこと。
  • 対象相手:行動の対象が特定の相手に偏らないこと。
  • ゆらぎ件数:月に3件以上のゆらぎを達成すること。

応用評価基準

  • 現波動レベル:各次元毎の各生命体での各レベルの行動を集計すること。
  • 現次元レベル:各次元毎の各生命体での行動を集計すること。
  • 目標到達度:申告した目標に対しての到達度を集計すること。
  • 役割経験数:役割の経験を集計すること。
  • 現役割等級:各次元毎の各生命体での役割の貢献度を集計すること。

評価プロセス

  1. データ収集

    • 各ユーザーの愛の行動データを月次で収集する。
    • 行動の日時、対象相手、次元、波動レベル、愛の行動量などのデータを記録する。
  2. コンピテンシーモデルの設定

    • 標準行動モデルを設定し、これに基づいて評価基準を設ける。
    • 時間の経過とともに基準を見直し、更新する。
  3. データ分析

    • 収集されたデータをもとに、各ユーザーの行動を評価する。
    • 偏りの分析には、標準偏差などの統計的手法を用いる。
  4. フィードバックの提供

    • 評価結果をユーザーにフィードバックする。
    • グラフやレポート形式で視覚的に表示し、自己理解を促進する。
       

現次元レベルの評価

次は、現次元レベル:各次元毎の各生命体での行動を集計すること、を測定したい。なお、次元の数を単純に集計するのでは無く、レベル毎に補正をかけて集計していくような設計にしていきたい。

・設計

次元ごとの各生命体での行動を集計し、次元レベルに補正をかけて集計する方法を設計する。

  1. 次元ごとの補正値の設定

    • 各次元に対して異なる補正値を設定する。低次元には低い補正値を、高次元には高い補正値を設定する。
    • 第1次元(個人):1
    • 第2次元(部署・チーム):2
    • 第3次元(会社):3
    • 第4次元(業界・協会):4
    • 第5次元(産業):5
    • 第6次元(日本):6
    • 第7次元(世界):7
    • 第8次元(人類):8
    • 第9次元(地球):9
    • 第10次元(太陽系):10
  2. 行動の記録

    • 各行動が記録される際に、次元ごとの補正値を考慮してスコアリングする。
  3. 評価方法

    • 各次元の行動数に補正値を掛けた合計スコアを計算する。
    • 合計スコアが最も高い次元を現次元とする。

以下は、現次元レベルを評価するプログラムの例である。

 

○スマートコントラクト(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 dimension_action {
    #[cfg(not(feature = "ink-as-dependency"))]
    use super::*;

    #[derive(scale::Encode, scale::Decode, Clone, Default)]
    #[cfg_attr(feature = "std", derive(Debug))]
    pub struct Action {
        user_id: String,
        dimension: String,
        entity: String,
        level: u32,
        timestamp: u64,
    }

    #[ink(storage)]
    pub struct DimensionAction {
        actions: StorageHashMap<AccountId, Vec<Action>>,
        entity_actions: StorageHashMap<String, StorageHashMap<String, u32>>, // entity -> (dimension -> count)
        dimension_weights: StorageHashMap<String, u32>, // dimension -> weight
    }

    impl DimensionAction {
        #[ink(constructor)]
        pub fn new() -> Self {
            let mut dimension_weights = StorageHashMap::new();
            dimension_weights.insert("個人".to_string(), 1);
            dimension_weights.insert("部署・チーム".to_string(), 2);
            dimension_weights.insert("会社".to_string(), 3);
            dimension_weights.insert("業界・協会".to_string(), 4);
            dimension_weights.insert("産業".to_string(), 5);
            dimension_weights.insert("日本".to_string(), 6);
            dimension_weights.insert("世界".to_string(), 7);
            dimension_weights.insert("人類".to_string(), 8);
            dimension_weights.insert("地球".to_string(), 9);
            dimension_weights.insert("太陽系".to_string(), 10);

            Self {
                actions: StorageHashMap::new(),
                entity_actions: StorageHashMap::new(),
                dimension_weights,
            }
        }

        #[ink(message)]
        pub fn record_action(&mut self, user_id: String, dimension: String, entity: String, level: u32) {
            let caller = self.env().caller();
            let timestamp = self.env().block_timestamp();

            let action = Action {
                user_id,
                dimension: dimension.clone(),
                entity: entity.clone(),
                level,
                timestamp,
            };

            self.actions.entry(caller).or_insert(Vec::new()).push(action);

            let entity_map = self.entity_actions.entry(entity.clone()).or_insert(StorageHashMap::new());
            let count = entity_map.entry(dimension.clone()).or_insert(0);
            *count += level; // levelを加算して補正を適用
        }

        #[ink(message)]
        pub fn get_actions(&self, account: AccountId) -> Vec<Action> {
            self.actions.get(&account).cloned().unwrap_or_default()
        }

        #[ink(message)]
        pub fn get_entity_action_count(&self, entity: String, dimension: String) -> u32 {
            match self.entity_actions.get(&entity) {
                Some(dimension_map) => match dimension_map.get(&dimension) {
                    Some(count) => *count,
                    None => 0,
                },
                None => 0,
            }
        }

        #[ink(message)]
        pub fn get_user_dimension_score(&self, account: AccountId) -> StorageHashMap<String, u32> {
            let actions = self.get_actions(account);
            let mut dimension_scores = StorageHashMap::new();

            for action in actions {
                let weight = self.dimension_weights.get(&action.dimension).cloned().unwrap_or(1);
                let score = dimension_scores.entry(action.dimension.clone()).or_insert(0);
                *score += weight * action.level; // 補正値と行動レベルを掛け合わせる
            }

            dimension_scores
        }

        #[ink(message)]
        pub fn get_current_dimension(&self, account: AccountId) -> Option<String> {
            let dimension_scores = self.get_user_dimension_score(account);
            let mut max_score = 0;
            let mut current_dimension = None;

            for (dimension, score) in dimension_scores.iter() {
                if *score > max_score {
                    max_score = *score;
                    current_dimension = Some(dimension.clone());
                }
            }

            current_dimension
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[ink::test]
        fn record_and_get_action_works() {
            let mut contract = DimensionAction::new();
            contract.record_action("user1".into(), "個人".into(), "entity1".into(), 1);
            let actions = contract.get_actions(AccountId::from([0x1; 32]));
            assert_eq!(actions.len(), 1);
            assert_eq!(actions[0].dimension, "個人");
            assert_eq!(actions[0].entity, "entity1");
        }

        #[ink::test]
        fn get_entity_action_count_works() {
            let mut contract = DimensionAction::new();
            contract.record_action("user1".into(), "個人".into(), "entity1".into(), 1);
            let count = contract.get_entity_action_count("entity1".into(), "個人".into());
            assert_eq!(count, 1);
        }

        #[ink::test]
        fn get_current_dimension_works() {
            let mut contract = DimensionAction::new();
            contract.record_action("user1".into(), "個人".into(), "entity1".into(), 1);
            contract.record_action("user1".into(), "会社".into(), "entity1".into(), 3);
            let current_dimension = contract.get_current_dimension(AccountId::from([0x1; 32]));
            assert_eq!(current_dimension, Some("会社".to_string()));
        }
    }
}

 

○DApps側のPythonプログラム:

from flask import Flask, request, jsonify
from web3 import Web3
import json

app = Flask(__name__)

# Web3の初期化
web3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

# スマートコントラクトのアドレスとABI
contract_address = '0xYourContractAddress'
with open('path_to_abi.json') as f:
    contract_abi = json.load(f)

contract = web3.eth.contract(address=contract_address, abi=contract_abi)

@app.route('/record_action', methods=['POST'])
def record_action():
    data = request.get_json()
    user_address = data['user_address']
    user_id = data['user_id']
    dimension = data['dimension']
    entity = data['entity']
    level = data['level']

    tx_hash = contract.functions.record_action(user_id, dimension, entity, level).transact({'from': user_address})
    receipt = web3.eth.waitForTransactionReceipt(tx_hash)
    return jsonify({"message": "Action recorded successfully", "receipt": receipt}), 200

@app.route('/get_current_dimension', methods=['POST'])
def get_current_dimension():
    data = request.get_json()
    user_address = data['user_address']

    current_dimension = contract.functions.get_current_dimension(user_address).call()
    return jsonify({"current_dimension": current_dimension})

if __name__ == '__main__':
    app.run(debug=True)
 

この設計と実装により、ユーザーが各次元ごとの各生命体に対して行動した履歴を記録し、そのデータを集計して、次元レベルに補正をかけて評価することが可能になる。補正値と次元レベルを掛け合わせることで、次元ごとの行動が集計され、最もスコアが高い次元を現次元として算出する。

 


いかがであろうか、これでプロフィール画面に次元レベルを表示させる仕組みができた。これで自分の次元レベルを知ることができる。参考値ではあるが、自分の次元レベルを知ることができれば、自分の行動をどのように変えていけばいいのかとか、もっとレベルを上げたいとか、欲求が芽生え、さらなる愛の行動をしていくことができるのであろう。