{ "cells": [ { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import time\n", "import pprint\n", "from datetime import datetime" ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "comments got removed\n", "{'data': {'client': 'some company',\n", " 'contractor': 'semmtech',\n", " 'discription': 'a sample project',\n", " 'name': 'project',\n", " 'people': ['astrix', 'obelix']},\n", " 'date of initiation': '2021-01-07 15:23:49',\n", " 'id': 0,\n", " 'initiated by': 'astrix',\n", " 'last update': '2021-01-07 15:23:49',\n", " 'terms': {'Sign time': 'not yet signed',\n", " 'accepted': False,\n", " 'deadline': '1 month',\n", " 'price': 10000,\n", " 'progress': '0%'},\n", " 'type': 'init'}\n", "\n", "\n", "\n", "\n", "{'data': {'client': 'The organization',\n", " 'contractor': 'not semmtech',\n", " 'discription': 'a real project',\n", " 'name': 'r project',\n", " 'people': ['samson', 'gert']},\n", " 'date of initiation': '2021-01-07 15:23:49',\n", " 'id': 1,\n", " 'initiated by': 'samson',\n", " 'terms': {'Sign time': 'not yet signed',\n", " 'accepted': False,\n", " 'comments': {},\n", " 'deadline': '31-12-2021',\n", " 'price': 10000,\n", " 'progress': '0%'},\n", " 'type': 'init'}\n", "\n", "\n", "\n", "\n", "{'data': {'client': 'The foundation',\n", " 'contractor': 'scp-096',\n", " 'discription': 'to contain 096',\n", " 'name': 'containment',\n", " 'people': ['doctor bright', '05-12']},\n", " 'date of initiation': '2021-01-07 15:23:49',\n", " 'id': 2,\n", " 'initiated by': '05-2',\n", " 'terms': {'Sign time': 'not yet signed',\n", " 'accepted': False,\n", " 'comments': {4: {'author': 'doctor bright',\n", " 'body': 'no im right 05-12 is defo wrong',\n", " 'contract': 2,\n", " 'time': '2021-01-07 15:23:49'}},\n", " 'deadline': '31-12-2021',\n", " 'price': 'at all costs',\n", " 'progress': '0%'},\n", " 'type': 'init'}\n", "\n", "\n", "\n", "\n", "[{2: {'author': 'doctor bright', 'body': 'needs to be terminated', 'time': '2021-01-07 15:23:49', 'contract': 2}}, {3: {'author': '05-12', 'body': 'doctor bright is wrong', 'time': '2021-01-07 15:23:49', 'contract': 2}}, {4: {'author': 'doctor bright', 'body': 'no im right 05-12 is defo wrong', 'time': '2021-01-07 15:23:49', 'contract': 2}}]\n", "7\n", "[{'accepted': True,\n", " 'change': {'deadline': '1 month'},\n", " 'id': 0,\n", " 'last update': '2021-01-07 15:23:49',\n", " 'type': 'modify',\n", " 'update id': 0,\n", " 'updated': 'deadline',\n", " 'updated by': 'obelix'}]\n" ] } ], "source": [ "# %%time\n", "\n", "class Chain():\n", " \n", " def __init__(self):\n", " \n", " # initialize the mock blockchain\n", " self.blockchain = []\n", " self.current_block = Block()\n", " \n", " # add old block to chain and create new block\n", " def new_block(self):\n", " self.blockchain.append(self.current_block)\n", " self.current_block = Block()\n", " pass\n", " \n", " # create new contract\n", " def new_contract(self, iden,client, contractor, deadline, discription, name, price, people, initiator):\n", " \n", " # set discriptors of contract\n", " contract = {'id':iden,\n", " 'type':'init',\n", " 'date of initiation':get_t(),\n", " 'initiated by': initiator,\n", " 'data': {'client':client,\n", " 'contractor':contractor,\n", " 'discription':discription,\n", " 'name':name,\n", " 'people': people},\n", " 'terms' : {'deadline': deadline,\n", " 'accepted': False,\n", " 'progress': '0%',\n", " 'price':price,\n", " 'Sign time': 'not yet signed',\n", " 'comments':{}\n", " }\n", " }\n", " \n", " # add as transaction\n", " self.current_block.add(contract)\n", " \n", " # If block to big, get new\n", " if self.current_block.size() > 10:\n", " self.new_block()\n", " \n", " # add updates to the contract\n", " def update_contract(self, iden, attr, value, by, comment=None):\n", " \n", " # check if transaction adds or modifies\n", " self.current_contract_state(iden)\n", " if attr in self.state['data'] or attr in self.state['terms']:\n", " t = 'modify'\n", " else: t = 'update'\n", " \n", " # add new or updated info to block\n", " update = {'id':iden,\n", " 'update id':len(self.get_updates(iden)), \n", " 'updated':attr,\n", " 'type':t,\n", " 'last update':get_t(),\n", " 'updated by':by,\n", " 'accepted': False,\n", " 'change':{attr:value}}\n", " \n", " # check if comment is passed and add it if necassary\n", " if comment:\n", " update['comment'] = comment\n", " \n", " # add transaction\n", " self.current_block.add(update)\n", " \n", " # check if new block is needed\n", " if self.current_block.size() > 10:\n", " self.new_block()\n", " \n", " # accept updates\n", " def accept_update(self, iden, update_id, awnser, by, comment=None):\n", " update = {\n", " 'id':iden,\n", " 'update id':update_id,\n", " 'accept':awnser,\n", " 'type':'accept',\n", " 'last update':get_t(),\n", " 'accepted by': by\n", " }\n", " if comment:\n", " update['comment'] = comment\n", " \n", " self.current_block.add(update)\n", " \n", " # check if new block is needed\n", " if self.current_block.size() > 10:\n", " self.new_block()\n", " \n", " # get current state of the contract\n", " def current_contract_state(self, iden):\n", " # set up contract state\n", " self.state = {'id':iden,\n", " 'data':{},\n", " 'terms':{}\n", " }\n", " \n", " b = []\n", " \n", " # loop over all blocks in the chain\n", " for block in self.blockchain:\n", " b += block.block \n", " \n", " # retreive all the data\n", " self.get_data(b + self.current_block.block, iden)\n", " \n", " # get all data and format it\n", " def get_data(self, transactions, iden):\n", " \n", " # save not yet approved updates\n", " updates = {}\n", " \n", " # loop over all transaction in block\n", " for item in transactions:\n", " \n", " # save data about our project\n", " if item['id'] == iden:\n", " \n", " # set state to inital contract state\n", " if item['type'] == 'init':\n", " self.state = item\n", " continue\n", " \n", " # if update is not accept update, save it to updates dict\n", " if item['type'] != 'accept':\n", " \n", " # comments are always accepted\n", " if item['updated'] != 'comments':\n", " updates[item['update id']] = item\n", " continue\n", " \n", " # if accepted is true, retrieve update form dict and add to contract state\n", " elif item['accept'] == True:\n", " item = updates[item['update id']]\n", " \n", " # set attr to whatever has been updated\n", " attr = item['updated']\n", " \n", " # check if the update was removal\n", " if item['type'] == 'remove':\n", " print(attr + ' got removed')\n", " \n", " # delete item in the right part of the dict\n", " try:\n", " if attr in self.state['data']:\n", " del self.state['data'][attr]\n", " else:\n", " del self.state['terms'][attr]\n", " except:\n", " pass\n", " \n", " if item['type'] == 'update':\n", " self.state['terms'][attr] = item['change'][attr]\n", " \n", " # check if updated attr is data or terms\n", " elif attr in self.state['data']:\n", " self.state['data'][attr] = item['change'][attr]\n", " \n", " elif attr in self.state['terms']:\n", " \n", " # special case for comments\n", " if attr == 'comments' and item['type'] not in ['remove', 'init']:\n", " k = list(item['change'][attr].keys())[0]\n", " self.state['terms'][attr][k] = item['change'][attr][k]\n", " \n", " # case for normal updates\n", " else: \n", " self.state['terms'][attr] = item['change'][attr]\n", " \n", " # special cases for last update and date of initiation\n", " elif 'last update' in item:\n", " self.state['last update'] = item['last update']\n", " \n", " # get updates based on contract, atribute updated or accept state\n", " def get_updates(self, iden=None, attr=None, accepted=None):\n", " updates = []\n", " \n", " # get all blocks and loop over transactions\n", " for block in self.blockchain + [self.current_block]:\n", " for item in block.block:\n", " \n", " # if attr is '' get updates for all attributes\n", " if attr == None:\n", " \n", " # if iden is None, get updates for all contracts\n", " # updates for all contracts and attrs\n", " if iden == None:\n", " if item['type'] != 'init':\n", " updates.append(item)\n", " \n", " # updates for specific contracts from all attr\n", " else:\n", " if item['type'] != 'init' and item['id'] == iden:\n", " updates.append(item)\n", " else:\n", " \n", " # updates for specific attrs from all contract\n", " if iden == None:\n", " if item['type'] != 'init' and item['updated'] == attr:\n", " updates.append(item)\n", " # updates for specific contract and specific attr\n", " else:\n", " print(item)\n", " if item['type'] != 'init' and item['updated'] == attr and item['id'] == iden:\n", " updates.append(item)\n", " return updates\n", " \n", " # add transaction to remove items\n", " def remove_item(self, iden, attr):\n", " \n", " # add transaction to remove item\n", " self.current_block.add({'id':iden, \n", " 'updated':attr ,\n", " 'type':'remove',\n", " 'last update':get_t(), \n", " 'accept':False,\n", " 'update id':len(self.get_updates(iden))})\n", " \n", " if self.current_block.size() > 10:\n", " self.new_block()\n", " \n", " # add comments to\n", " def add_comment(self, iden, body, author):\n", " \n", " # get all updates for comments\n", " comment_updates = []\n", " for block in self.blockchain + [self.current_block]:\n", " for item in block.block:\n", " if 'updated' in item:\n", " if item['updated'] == 'comments':\n", " comment_updates.append(item)\n", " \n", " # create transaction\n", " self.current_block.add({'id':iden,\n", " 'updated':'comments',\n", " 'accept':True,\n", " 'type':'update',\n", " 'last update':get_t(),\n", " 'change':{'comments':{len(comment_updates):{'author':author,\n", " 'body': body, \n", " 'time': get_t(),\n", " 'contract':iden}}}})\n", " if self.current_block.size() > 10:\n", " self.new_block()\n", " \n", " # retrieve comments based on author and contract\n", " def retrieve_comments(self, iden=None, author = None):\n", " comment = []\n", " \n", " # check every block in the chain\n", " for block in self.blockchain + [self.current_block]:\n", " for item in block.block:\n", " \n", " # if transaction is of type init, skip it\n", " if item['type'] == 'init' or item['type'] == 'accept':\n", " continue\n", " \n", " # check if the update is a comment \n", " if item['updated'] == 'comments':\n", " \n", " #filters for contract and author\n", " # no contract or author filter\n", " if iden == None and author == None:\n", " comment.append(item['change']['comments'])\n", "\n", " # filter by contract\n", " elif iden != None and author == None:\n", " if item['id'] == iden:\n", " comment.append(item['change']['comments'])\n", " \n", " # filter by author\n", " elif iden == None and author != None:\n", " if list(item['change']['comments'].values())[0]['author'] == author:\n", " comment.append(item['terms']['comments'])\n", " \n", " # filter by author and contract\n", " elif iden != None and author != None:\n", " if item['id'] == iden and list(item['change']['comments'].values())[0]['author'] == author:\n", " comment.append(item['change']['comments'])\n", " return comment\n", " \n", " # get updates for a contract that have to be accepted or are already accepted\n", " def retrieve_updates(self, iden, accepted=None):\n", " \n", " updates = {}\n", " \n", " # get all updates for a contract\n", " all_updates = self.get_updates(iden = iden, accepted = accepted)\n", " \n", " for item in all_updates:\n", " if item['type'] != 'accept' and item['updated'] != 'comments':\n", " updates[item['update id']] = item\n", " else:\n", " try:\n", " updates[item['update id']]['accepted'] = item['accept']\n", " except:\n", " pass\n", " \n", " if accepted == None:\n", " return updates \n", " \n", " return [updates[x] for x in list(updates.keys()) if updates[x]['accepted'] == accepted]\n", " \n", " def __str__(self):\n", " print(self.current_block)\n", " return ''\n", " \n", " \n", "class Block():\n", " \n", " # init block\n", " def __init__(self):\n", " self.block = []\n", " \n", " # add new transactions\n", " def add(self, contract):\n", " self.block.append(contract)\n", " \n", " # get size of block\n", " def size(self):\n", " return len(self.block)\n", " \n", " def __str__(self):\n", " pprint.pprint(self.block)\n", " return ''\n", "\n", "def get_t():\n", " return datetime.utcfromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')\n", "\n", "\n", "\n", "chain = Chain()\n", "# create contracts\n", "people = ['astrix', 'obelix']\n", "chain.new_contract(0, 'some company', 'semmtech', 'two weeks', 'a sample project', 'project', 10000, people, 'astrix')\n", "people = ['samson', 'gert']\n", "chain.new_contract(1, 'The organization', 'not semmtech', '31-12-2021', 'a real project', 'r project', 10000, people, 'samson')\n", "people = ['doctor bright', '05-12']\n", "chain.new_contract(2, 'The foundation', 'scp-096', '31-12-2021', 'to contain 096', 'containment', 'at all costs', people, '05-2')\n", "\n", "# updates for contract 0\n", "chain.update_contract(0, 'deadline', '1 month', 'obelix')\n", "chain.accept_update(0, 0, True, 'astrix')\n", "chain.update_contract(0, 'progress', '50%', 'astrix' ,'we done with 50 %')\n", "chain.update_contract(0, 'discription', 'A project sample', 'obelix')\n", "chain.update_contract(0, 'progress', '75%', 'astrix')\n", "chain.add_comment(0, 'I like the progress', 'astrix')\n", "\n", "\n", "# updates for contract 1\n", "chain.update_contract(1, 'accepted', True, 'gert')\n", "chain.update_contract(1, 'Sign time', get_t(), 'gert')\n", "chain.update_contract(1, 'name', 'actual project', 'samson')\n", "chain.update_contract(1, 'price', 16969, 'gert')\n", "chain.remove_item(0, 'comments')\n", "\n", "# updates for contract 2\n", "chain.add_comment(2, 'needs to be terminated', 'doctor bright')\n", "chain.add_comment(2, 'doctor bright is wrong', '05-12')\n", "chain.add_comment(2, 'no im right 05-12 is defo wrong', 'doctor bright')\n", "chain.update_contract(2, 'test term', 'works', '05-2')\n", "\n", "# show current state of contract 0\n", "chain.current_contract_state(0)\n", "pprint.pprint(chain.state)\n", "print('\\n\\n\\n')\n", "\n", "# show current state of contract 1\n", "chain.current_contract_state(1)\n", "pprint.pprint(chain.state)\n", "print('\\n\\n\\n')\n", "\n", "# show current state of contract 2\n", "chain.current_contract_state(2)\n", "pprint.pprint(chain.state)\n", "print('\\n\\n\\n')\n", "\n", "# retrieve comments\n", "print(chain.retrieve_comments(iden = 2))\n", "\n", "# retrieve block size\n", "print(chain.current_block.size())\n", "\n", "# retrieve updates\n", "pprint.pprint(chain.retrieve_updates(0, True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Todo: \n", "linking to other contracts \n", "milestones \n" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n" ] } ], "source": [ "if (True or False) and (False and True):\n", " print(True)\n", "else:\n", " print(False)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }