Porting from jupiter lab 😨
commit
ad06b349dc
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "5fbf751c-841f-4089-8ef0-5267356a069b",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from PIL import Image\n",
|
||||||
|
"import os\n",
|
||||||
|
"UPLOAD_FOLDER = os.path.join(os.getcwd(), 'static/uploads/annotation-compass/')\n",
|
||||||
|
"\n",
|
||||||
|
"def thumbnail(image):\n",
|
||||||
|
" try:\n",
|
||||||
|
" img = Image.open(image)\n",
|
||||||
|
" img.thumbnail((128,128))\n",
|
||||||
|
" name = image.rsplit('.', 1)[0]\n",
|
||||||
|
" ext = image.rsplit('.', 1)[1]\n",
|
||||||
|
" img.save(f'{name}_thumb.{ext}')\n",
|
||||||
|
" except IOError:\n",
|
||||||
|
" pass\n",
|
||||||
|
" \n",
|
||||||
|
"files = os.listdir(UPLOAD_FOLDER)\n",
|
||||||
|
"\n",
|
||||||
|
"for file in files:\n",
|
||||||
|
" thumbnail(os.path.join(UPLOAD_FOLDER, file))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "b65ddab7-a74d-4c32-8f70-ab9e21388a55",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
break_messages = [
|
||||||
|
"sorry I fell asleep come back in 10 min",
|
||||||
|
"Sorry I'm not available at the moment",
|
||||||
|
"sorry, i went to the toilet, see u back in 5 min",
|
||||||
|
"ehm, refresh the page in 3 min",
|
||||||
|
"ah i went on a break, you should go on a break too"
|
||||||
|
"Ah! you are here! I wasn't excepting of you! Wait to put something on me"
|
||||||
|
"I wasn't ready for this connection. I am a bit moody right now, so I am concentrating on finding my center."
|
||||||
|
"Upss I am having a break right now, cuddling my cat."
|
||||||
|
]
|
@ -0,0 +1,126 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 88,
|
||||||
|
"id": "e7bd7834-0370-4685-ae24-cd7faa6e08f9",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from error_messages import break_messages\n",
|
||||||
|
"import random, datetime, time\n",
|
||||||
|
"from datetime import date\n",
|
||||||
|
"import pytz"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 89,
|
||||||
|
"id": "74347109-d30a-476a-b903-cd3fa5b9274a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def random_line(txt_list):\n",
|
||||||
|
" message= choice(txt_list)\n",
|
||||||
|
" print (message)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 90,
|
||||||
|
"id": "8d527146-7473-4f02-b23e-61057a15a770",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"sorry I fell asleep come back in 10 min\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"random_line(break_messages)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "5d303ab1-47c1-4467-858b-7d84dc257e36",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 91,
|
||||||
|
"id": "8ba06a30-a28d-49cf-84d6-af1416945261",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"today = date.today()\n",
|
||||||
|
"altro = ('2021-12-15')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 92,
|
||||||
|
"id": "07738cdb-46cb-46ba-bf7e-2ed8813a3ff7",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2021-12-15\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"if today != altro:\n",
|
||||||
|
" print(altro)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 93,
|
||||||
|
"id": "7b28edc8-8762-4834-84b5-b7ca913902c3",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"tz = pytz.timezone('Europe/Berlin')\n",
|
||||||
|
"moment = datetime.datetime.now(tz)\n",
|
||||||
|
"timestamp = moment.__str__()\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "aaea2507-5bd0-4930-bf78-ed3ad9622276",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,317 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "aecab081-a69a-4e38-9a30-cfc95661e56b",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from urllib.request import urlopen\n",
|
||||||
|
"import json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "9538705e-e51e-49da-b4fe-e6c4c6f6c435",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Area Map:\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Select a specific area of the image, return a list of all labels in that specific area."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "13246f4a-81ac-4b68-b974-ae04064d10cc",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# function for the project!\n",
|
||||||
|
"# please, kamo, put it in the flask app! thxxxx\n",
|
||||||
|
"# (combined with html_tag_list)\n",
|
||||||
|
"\n",
|
||||||
|
"url = \"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=rejection_map.jpg/\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"def area_map_list(labels: list, left: int, right: int, top: int, bottom: int ) -> list: \n",
|
||||||
|
" \n",
|
||||||
|
" filtered_map = []\n",
|
||||||
|
" for label in labels:\n",
|
||||||
|
" if left <= (label['position']['x']) <= right and top <= (label['position']['y']) <= bottom:\n",
|
||||||
|
" filtered_map.append(label)\n",
|
||||||
|
" \n",
|
||||||
|
" return filtered_map\n",
|
||||||
|
"\n",
|
||||||
|
"#area_map_list(data_json['labels'], 0, 10, 30, 70)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "34b43aae-0830-47ca-86c9-5827bfa44cef",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Ghost Map:\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Replace all characters of all annotation-texts with a ghost-glyph and return a string that includes all replaced annotation-texts plus html-tags that place them back into their original position."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "dcbe893c-d00a-4933-9a18-8216a5f7459a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# function for the project!\n",
|
||||||
|
"# please, kamo, put it in the flask app! thxxxx\n",
|
||||||
|
"# this function links to jian.css\n",
|
||||||
|
"\n",
|
||||||
|
"url = \"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=rejection_map.jpg/\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"def ghost_map_list(labels: list, ghost_glyph: str ) -> str:\n",
|
||||||
|
" \n",
|
||||||
|
" filtered_map = '<link rel=\"stylesheet\" href=\"/soupboat/si16-app/static/css/jian.css\">'\n",
|
||||||
|
" for label in labels:\n",
|
||||||
|
" replaced_text = ''\n",
|
||||||
|
" for char in label['text']:\n",
|
||||||
|
" replaced_char = char\n",
|
||||||
|
" if not char.isspace():\n",
|
||||||
|
" replaced_char = ghost_glyph\n",
|
||||||
|
" replaced_text = replaced_text + replaced_char\n",
|
||||||
|
" html_tag = f'<p class=\"ghost\" style=\"left: {label[\"position\"][\"x\"]}%; top: {label[\"position\"][\"y\"]}%; position: absolute;\">{ replaced_text }</p>'\n",
|
||||||
|
" filtered_map = filtered_map + html_tag\n",
|
||||||
|
" return filtered_map\n",
|
||||||
|
"\n",
|
||||||
|
"#ghost_map_list(data_json['labels'], '.')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "863a6716-d9e4-413f-a597-a16cc0f04d6d",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Highlight Map:\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Give a target-word; Return a string that includes all annotation-texts plus html-tags that place them back into their original position while highlighting the annotation-texts that include the target."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "18cfc4fa-4039-49fe-8b29-5bbec0e89b6f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# function for the project!\n",
|
||||||
|
"# please, kamo, put it in the flask app! thxxxx\n",
|
||||||
|
"# this function links to jian.css\n",
|
||||||
|
"\n",
|
||||||
|
"url = \"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=rejection_map.jpg/\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"def highlight_map_list(labels: list, target: str ) -> str:\n",
|
||||||
|
"\n",
|
||||||
|
" filtered_map = '<link rel=\"stylesheet\" href=\"/soupboat/si16-app/static/css/jian.css\">'\n",
|
||||||
|
" for label in labels:\n",
|
||||||
|
" if target in label['text']:\n",
|
||||||
|
" highlight_tag = f'<p class=\"highlight\" style=\"left: {label[\"position\"][\"x\"]}%; top: {label[\"position\"][\"y\"]}%; position: absolute;\">{ label[\"text\"] }</p>'\n",
|
||||||
|
" filtered_map = filtered_map + highlight_tag\n",
|
||||||
|
" else:\n",
|
||||||
|
" html_tag = f'<p class=\"lowlight\" style=\"left: {label[\"position\"][\"x\"]}%; top: {label[\"position\"][\"y\"]}%; position: absolute;\">{ label[\"text\"] }</p>'\n",
|
||||||
|
" filtered_map = filtered_map + html_tag\n",
|
||||||
|
" \n",
|
||||||
|
" return filtered_map\n",
|
||||||
|
"\n",
|
||||||
|
"#highlight_map_list(data_json['labels'], 'tunnel')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "9c41f5fd-1071-43b3-88bc-41a8e5907fdb",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"html-tag:\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Return a string that can include the position, text, timestamp and/or userID of all labels plus html-tags that place them back into their original position."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "a7ee1bdf-a356-4a66-aa01-ef1dad8738ca",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# function for the project!\n",
|
||||||
|
"# please, kamo, put it in the flask app! thxxxx\n",
|
||||||
|
"# this function links to jian.css\n",
|
||||||
|
"\n",
|
||||||
|
"url = \"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=rejection_map.jpg/\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"def html_tag_list(labels: list, position: bool, text: bool, timestamp: bool, userID: bool ) -> str: \n",
|
||||||
|
" \n",
|
||||||
|
" html_tags = '<link rel=\"stylesheet\" href=\"/soupboat/si16-app/static/css/jian.css\">'\n",
|
||||||
|
" for label in labels:\n",
|
||||||
|
" html_tags = html_tags + f'<p style=\"left: {label[\"position\"][\"x\"]}%; top: {label[\"position\"][\"y\"]}%; position: absolute;\">'\n",
|
||||||
|
" if position == True:\n",
|
||||||
|
" html_position = f'{ label[\"position\"] } '\n",
|
||||||
|
" html_tags = html_tags + html_position\n",
|
||||||
|
" if text == True:\n",
|
||||||
|
" html_text = f'{ label[\"text\"] } '\n",
|
||||||
|
" html_tags = html_tags + html_text\n",
|
||||||
|
" if timestamp == True:\n",
|
||||||
|
" html_timestamp = f'{ label[\"timestamp\"] } '\n",
|
||||||
|
" html_tags = html_tags + html_timestamp\n",
|
||||||
|
" if userID == True:\n",
|
||||||
|
" html_userID = f'{ label[\"userID\"] } '\n",
|
||||||
|
" html_tags = html_tags + html_userID\n",
|
||||||
|
" html_tags = html_tags + '</p>'\n",
|
||||||
|
" \n",
|
||||||
|
" return html_tags\n",
|
||||||
|
"\n",
|
||||||
|
"#html_tag_list(data_json['labels'], True, False, False, False)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d05dd98e-0cdb-4a50-839a-7a67cdc22010",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Individual Map:\n",
|
||||||
|
"give a string with the name of the image-file that was annotated with the Annotation Compass; Select one or more specific targets and return a list of all labels that include these targetsselect one or more specific users and return a list of all labels from these users."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 9,
|
||||||
|
"id": "e8d7824d-4523-46f7-b89f-0e8f2d98e564",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# function for the project!\n",
|
||||||
|
"# hei kamo! is it already in the flask? should be?\n",
|
||||||
|
"# (combined with html_tag_list)\n",
|
||||||
|
"\n",
|
||||||
|
"url = \"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=rejection_map.jpg/\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"def individual_map_list(labels: list, users: list ) -> list: \n",
|
||||||
|
" \n",
|
||||||
|
" filtered_map = []\n",
|
||||||
|
" for label in labels:\n",
|
||||||
|
" for user in users:\n",
|
||||||
|
" if label['userID'] == user:\n",
|
||||||
|
" filtered_map.append(label)\n",
|
||||||
|
" return filtered_map\n",
|
||||||
|
"\n",
|
||||||
|
"#individual_map_list(data_json['labels'], ['5058763759', '5941298752'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "0f3febed-e702-4585-a7a1-e62d1a16d1c0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Target Map:\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Select one or more specific targets and return a list of all labels that include these targets"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "9d263750-bab0-4989-9074-a58eba21b2c5",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# function for the project!\n",
|
||||||
|
"# please, kamo, put it in the flask app! thxxxx\n",
|
||||||
|
"# (combined with html_tag_list)\n",
|
||||||
|
"\n",
|
||||||
|
"url = \"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=rejection_map.jpg/\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"def target_map_list(labels: list, targets: list ) -> list: \n",
|
||||||
|
" \n",
|
||||||
|
" filter_map = []\n",
|
||||||
|
" for label in labels:\n",
|
||||||
|
" for target in targets:\n",
|
||||||
|
" if target in label['text']:\n",
|
||||||
|
" filter_map.append(label)\n",
|
||||||
|
" return filter_map\n",
|
||||||
|
"\n",
|
||||||
|
"#target_map_list(data_json['labels'], ['tunnel', 'happy'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a8e5a256-b9e6-4f0f-b395-690c36d88a7e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Vernacular Map:\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Return a string that includes all annotation-texts plus html-tags that place them back into their original position."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"id": "d78dca69-5f1e-408d-85b5-6cc594f2f875",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# function for the project!\n",
|
||||||
|
"# please, kamo, put it in the flask app! thxxxx\n",
|
||||||
|
"# this function links to jian.css\n",
|
||||||
|
"\n",
|
||||||
|
"url = \"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=rejection_map.jpg/\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"def vernacular_map_list(labels: list) -> str: \n",
|
||||||
|
"\n",
|
||||||
|
" filtered_map = '<link rel=\"stylesheet\" href=\"/soupboat/si16-app/static/css/jian.css\">'\n",
|
||||||
|
" for label in labels:\n",
|
||||||
|
" html_tag = f'<p style=\"left: {label[\"position\"][\"x\"]}%; top: {label[\"position\"][\"y\"]}%; position: absolute;\">{ label[\"text\"] }</p>'\n",
|
||||||
|
" filtered_map = filtered_map + html_tag\n",
|
||||||
|
" \n",
|
||||||
|
" return filtered_map\n",
|
||||||
|
"\n",
|
||||||
|
"#vernacular_map_list(data_json['labels'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "6a207852-701e-48ef-8469-96c245aea6a4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "1d499616-2ed6-49c5-a3f3-394f5330dd1f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "96517076-dff6-4e43-b858-0215eb5e538e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# --------ETC PORTAL------------ #\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f'/{base_url}/api/')\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~chae/api/\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f'/{base_url}/the-etc-portal-is-open/')\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~chae/api/the-etc-portal-is-open/\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f'/{base_url}/start-contaminating/', methods = ['GET'])\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~chae/api/start-contaminating/\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f'/{base_url}/the-etc-portal-is-never-opened/', methods = ['GET', 'POST'])\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~chae/api/the-etc-portal-is-never-opened/ \n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f'/{base_url}/the-etc-portal-is-closed/', methods = ['GET', 'POST'])\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~chae/api/the-etc-portal-is-closed/\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# --------AND I WISH THAT YOUR QUESTION HAS BEEN ANSWERED------------ #\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(\"/{base_url}/and_i_wish_that_your_question_has_been_answered/\", methods=['GET', 'POST'])\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~grgr/api/and_i_wish_that_your_question_has_been_answered/\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f\"/{base_url}/archive/\", methods=['GET'])\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~grgr/api/archive/\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f\"/{base_url}/save/\", methods=['GET', 'POST'])\n",
|
||||||
|
"https://hub.xpub.nl/soupboat/~grgr/api/save/\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# --------VERNACULAR MAPS------------ #\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f\"/{base_url}/annotation-compass/\", methods=['GET', 'POST'])\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f\"/{base_url}/annotation-compass/annotate/<image>/\", methods=['GET', 'POST'])\n",
|
||||||
|
"\n",
|
||||||
|
"@app.route(f\"/{base_url}/annotation-compass/get-labels/<image>\", methods=['GET', 'POST'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "56987d98-84ba-43c9-88a9-fc365cca2ecc",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: Corpora
|
||||||
|
description: Information About the SI16's Corpora
|
||||||
|
url:
|
||||||
|
---
|
||||||
|
|
||||||
|
## INFO
|
||||||
|
|
||||||
|
The functions from the Special Issue 16 were built to experiment and play around with vernacular language processing. Before a tool can replace, contaminate, reverse or mashup, it needs textual material as an input.
|
||||||
|
|
||||||
|
Here we gather corpora, small collections of linguistic data that were inspiring and useful in our research, experiments or projects.
|
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: Functions
|
||||||
|
description: Information About the SI16's Functions
|
||||||
|
url:
|
||||||
|
---
|
||||||
|
|
||||||
|
## INFO
|
||||||
|
|
||||||
|
The functions from the Special Issue 16 have been freshly delivered into this world for you. Our first steps into the realm of Language Processing, our first attempts at Vernacular Language Processing.
|
||||||
|
|
||||||
|
What we share with you here are stripped-out functions we made use of in our tools. Some might still need more context than others, but essentially they can be used in different fashions depending of the users' wants and needs.
|
||||||
|
|
||||||
|
We wanted you, whoever you are: friend or online scroller, beloved internet user or binge watcher, even IRL human being … whoever you are! We wanted us to share with you how our tools came to life, expose the internal mechanism to the text processing you are about to engage with.
|
||||||
|
|
||||||
|
You didn't quite get it? Basically, our project is meant to give a bunch of users several tools such as : ✂️ scissors, 📃 sticky notes, ✏️ pencils, erasers, and printed paper. ✂️🖊📝✏️📃 And let them have fun. Cutting it and putting it together, making notes and writing jokes … But everything in a digital format.
|
||||||
|
|
||||||
|
Have a look around and have fun!
|
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: License
|
||||||
|
description: Information About the SI16's License
|
||||||
|
url:
|
||||||
|
---
|
||||||
|
|
||||||
|
------------------------------------------Catleft License--------------------------------------------
|
||||||
|
|
||||||
|
The Catleft license wants to legitimise failures, promote critical approaches, and embrace the user as co-author.
|
||||||
|
|
||||||
|
Conditions for reuse:
|
||||||
|
1. Any reproduction or redistribution of the material under this license has to be readable by both humans and machines.
|
||||||
|
2. It is adviced to use, reproduce, modify and redistribute the material according to the user's own language and dialect.
|
||||||
|
3. The material can be reproduced, distributed, or transmitted in any form, by any means, and any purpose except for commercial purposes. In this case, the material can only be reused with the written permission of one of the license holders. For permission requests, write to XPUB department.
|
||||||
|
4. Always include this license with the distribution of your project or specify where it can be found it.
|
||||||
|
Make a copy of the text of the license and paste it with the date and name of the license holder. Put this license file in the root directory of your project repository and include it with the distribution of your project.
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
title: Projects
|
||||||
|
description: Information About the SI16's Projects
|
||||||
|
url:
|
||||||
|
---
|
||||||
|
|
||||||
|
## INFO
|
||||||
|
|
||||||
|
The projects from the Special Issue 16 have accompanied us on our way to build this toolkit. Whereas our practice shaped the functions we created, the tools formed our projects to a similar extent.
|
||||||
|
|
||||||
|
Each of them is an experimental adventure, elaborating on different aspects of vernacular language processing while inviting users to participate. Come with us to see how our functions come to life and join us in this fearless and joyful undertaking.
|
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<form action='https://hub.xpub.nl/soupboat/si16-app/api/cocktail_generator/'>
|
||||||
|
<input class='list-input' type="text" name='alcohol'>
|
||||||
|
<input class='list-input' type="text" name='decor'>
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script src="/soupboat/si16-app/static/js/inputList.js" defer ></script>
|
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
title: Terms of Service
|
||||||
|
description: Terms of Service SI16
|
||||||
|
css: tos.css
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vernacular catwalking, learning and teaching.
|
||||||
|
|
||||||
|
Our API (Application Programming Interface) is in itself an experiment to legitimise failures, promote a more critical approach to APIs as models of distribution, and embrace the user as co-author. It is accessible both in html and json format. The aim of this ToS is to articulate inclusive conditions for vernacular catwalking, learning and teaching.
|
||||||
|
|
||||||
|
### 0. Access
|
||||||
|
|
||||||
|
This service can be used by any individual persons, organizations, institutions or collectives that are willing to reject any sort of stigma towards languange, ignore grammar correctness and officiality, both in oral and written language, and who are interested in vernacular amatorial practices around and within language processing and the use that is made of it.
|
||||||
|
|
||||||
|
### 1. By using this service, you agree on the following:
|
||||||
|
|
||||||
|
1. All the code and the contents produced through this API are automatically licensed under the _catleft license_
|
||||||
|
2. the API key comes in the form of a physical keychain and shall not be distributed through any other media different than the physical keychain itself.
|
||||||
|
3. The API key is held by a rotating "guardian" who:
|
||||||
|
1. shall leave a contact on the page _____ in order to be reached.
|
||||||
|
2. is responsible of adding the new API key to the keychain if modified.
|
||||||
|
3. is open to and seeks for collective consultation about the changes made to the API
|
||||||
|
4. The API key can be used for max. 10 days. After whose expiration it must be passed onto another guardian.
|
||||||
|
5. no personal data is collected, except for the contact of the guardian of the API-key
|
||||||
|
|
||||||
|
### 2. Privileges granted by the key
|
||||||
|
|
||||||
|
1. it allows to modify the API key; in this case the new API key must be added, in any physical form, as keychain gadget to the API key.
|
||||||
|
2. It allows to add new error messages, which shall include messages of self-care, encouragement, anecdotes about cats, common saying in any dialect, and/or favourite recipes.
|
||||||
|
3. it allows to access the complete hidden reading list and to add new suggestions.
|
||||||
|
|
||||||
|
Note: we reserve the right to modify or delete contributions that are homophobic, transphobic, racist, ableist and sexist, even if intended as a joke, or as an ironic remark. Same for hate speech, such as, but not limited to: white supremacy, ethnostate advocacy, discussion of national socialism / nazism.
|
||||||
|
|
||||||
|
### 3. How to pass on the key
|
||||||
|
|
||||||
|
The current guardian of the API-key shall pass the API-key to another person of their choice at the expiring of the 10 days.
|
||||||
|
|
||||||
|
### 4. Contacts
|
@ -0,0 +1,123 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "e839d993-7f9e-4419-92de-eb3dba046640",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# add_pen_name"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b87b3999-97c7-43da-9931-27f319a9f590",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"___\n",
|
||||||
|
"\n",
|
||||||
|
"Add pen names into the list<br> \n",
|
||||||
|
"\n",
|
||||||
|
"<img src=\"https://hub.xpub.nl/soupboat/~chae/break-it-down.jpeg\">"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "cf3788e7-7b88-480a-8a4e-8c53eae169e3",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Input:\n",
|
||||||
|
"- name, string"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "96ccfe4d-a20d-42e6-ad2c-fdfaa6fd2fc5",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"Output:\n",
|
||||||
|
"- name, list"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "4a5f59ac-bdfd-4695-8842-80db12bd156e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"pen_name_list = ['Blibli', 'Chae as Che Gueverq', 'turtle teller']\n",
|
||||||
|
"\n",
|
||||||
|
"def add_pen_name(name_input):\n",
|
||||||
|
" '''add pen name inside the list'''\n",
|
||||||
|
" if name_input:\n",
|
||||||
|
" if name_input not in pen_name_list:\n",
|
||||||
|
" pen_name_list.append(name_input)\n",
|
||||||
|
" return pen_name_list"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "a9668cd3-54a4-4e1b-baed-f8453965f693",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"['Blibli', 'Chae as Che Gueverq', 'turtle teller', 'broggle']"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# simple application here\n",
|
||||||
|
"add_pen_name('broggle')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "5db35904-9350-428d-9744-a922ebd05784",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"___\n",
|
||||||
|
"This function is part of C and G project, ***ETC Portal to Contaminate*** "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "919fd920-f52f-4912-b4e2-d5aa57c5f400",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "66f72396-0cf1-41cf-a486-2930d2ad1652",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# area_map\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Select a specific area of the image, return a list of all labels in that specific area."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "1eb5f9a2-a86a-45f2-aa7b-9b32653f9fed",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from urllib.request import urlopen\n",
|
||||||
|
"import json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "5fb4d7db-9d58-4921-81e9-9e5fd00c4d46",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def area_map(image: str, left: int, right: int, top: int, bottom: int ) -> list:\n",
|
||||||
|
" \n",
|
||||||
|
" \"\"\"Give a string with the name of the image-file that was annotated with the Annotation Compass; Select a specific area of the image, return a list of all labels in that specific area.\"\"\" \n",
|
||||||
|
"\n",
|
||||||
|
" url = f\"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image={image}\"\n",
|
||||||
|
" response = urlopen(url)\n",
|
||||||
|
" data_json = json.loads(response.read()) \n",
|
||||||
|
" \n",
|
||||||
|
" filtered_map = []\n",
|
||||||
|
" for label in data_json['labels']:\n",
|
||||||
|
" if left <= (label['position']['x']) <= right and top <= (label['position']['y']) <= bottom:\n",
|
||||||
|
" filtered_map.append(label)\n",
|
||||||
|
" \n",
|
||||||
|
" return filtered_map"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "1094ed8e-1387-481e-b612-9a8cc81d5c18",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This function was built for a project where individuals are invited to add their annotations on a map using the Annotation Compass. Each annotation-label is stored in a json-file and includes the annotation-text itself, but also the name of the image-file as well as the position, size, index, timestamp and userID of the annotation.\n",
|
||||||
|
"\n",
|
||||||
|
" Example for a label:\n",
|
||||||
|
"\n",
|
||||||
|
" {'image': 'map.jpg',\n",
|
||||||
|
" 'position': {'x': 12, 'y': 97},\n",
|
||||||
|
" 'size': {'width': 43, 'height': 18},\n",
|
||||||
|
" 'text': 'This is a text! Is this a text?',\n",
|
||||||
|
" 'timestamp': 'Wed, 01 Dec 2021 14:04:00 GMT',\n",
|
||||||
|
" 'userID': 5766039063}\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"If interested in the annotations in a specific area of the map, area_map() can help. The function needs a string with the name of the of the image-file that was annotated with the annotation compass tool as well as four specific values to define the left, right, top and bottom outlines of the selected area. The output is a list of all labels in the defined area of interest.\n",
|
||||||
|
"\n",
|
||||||
|
"How to get a json-file with annotation-labels?\n",
|
||||||
|
"\n",
|
||||||
|
" https://hub.xpub.nl/soupboat/generic-labels/\n",
|
||||||
|
"The Annotation Compass allows people to uplaod an image and ask others to annotate it. A json-file of the annotations is provided."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2c3e992a-317b-4433-8c3b-9efcedea575d",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Examples\n",
|
||||||
|
"\n",
|
||||||
|
"In this example, the function returns all annotation-labels in an area of interest that reaches from x = 70% to x = 90% and from y = 10% to y = 100%"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "e3d7e97b-0089-4c29-a2c1-9ef823ff2e37",
|
||||||
|
"metadata": {
|
||||||
|
"scrolled": true,
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[{'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 76.25, 'y': 69.5246},\n",
|
||||||
|
" 'size': {'height': 12.3939, 'width': 15.625},\n",
|
||||||
|
" 'text': \"I once went to view a house here but it didn't have the floor. crap.\",\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:36:51 GMT',\n",
|
||||||
|
" 'userID': '6286616941'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 77.0, 'y': 63.7521},\n",
|
||||||
|
" 'size': {'height': 8.65874, 'width': 10.25},\n",
|
||||||
|
" 'text': 'other housing rejection situations here.\\n',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:37:25 GMT',\n",
|
||||||
|
" 'userID': '6286616941'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 75.285, 'y': 29.2254},\n",
|
||||||
|
" 'size': {'height': 19.0141, 'width': 17.513},\n",
|
||||||
|
" 'text': '어딘지 잘은 모르겠지만, Kralingen 쪽이었던 것 같아. bsn 거주등록을 위해 학교에 갔는데, 시청에서 나온 사람들이 나의 룸메이트 ID card가 필요하다며 거절했지. 나의 아침을 날렸어. 나의 룸메가 나에게 ID card 사진을 보내줬지만, 그들은 서명이 같지 않다면서 다시 거절했지. ',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:39:21 GMT',\n",
|
||||||
|
" 'userID': '8633793842'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 73.703, 'y': 49.514},\n",
|
||||||
|
" 'size': {'height': 5.22479, 'width': 5.09839},\n",
|
||||||
|
" 'text': \"i got rejected from a skateboard here. it's normal though because it's always trying to reject you and you love it anyway\",\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:44:35 GMT',\n",
|
||||||
|
" 'userID': '8918562766'}]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"area_map('rejection_map.jpg', 70, 90, 10, 100)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "926c7209-4a91-4401-a1a5-15066b0331bc",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,327 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 179,
|
||||||
|
"id": "3c7f546e-2a12-456d-be2b-a01df62c32f4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"image = 'think-classify.jpg'\n",
|
||||||
|
"image2 = 'think-classify2.jpg'\n",
|
||||||
|
"image3 = 'think-classify3.jpg'\n",
|
||||||
|
"image4 = 'think-classify4.jpg'\n",
|
||||||
|
"image5 = 'think-classify5.jpg'\n",
|
||||||
|
"image6 = 'think-classify6.jpg'\n",
|
||||||
|
"image7 = 'think-classify7.jpg'\n",
|
||||||
|
"image8 = 'think-classify8.jpg'\n",
|
||||||
|
"image9 = 'think-classify9.jpg'\n",
|
||||||
|
"image10 = 'think-classify10.jpg'\n",
|
||||||
|
"image11 = 'think-classify11.jpg'\n",
|
||||||
|
"image12 = 'think-classify12.jpg'\n",
|
||||||
|
"image13 = 'think-classify13.jpg'\n",
|
||||||
|
"image14 = 'think-classify14.jpg'\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 198,
|
||||||
|
"id": "42b71c63-544e-4e39-9182-f5d349eb5389",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"[['to', 'meet,', 'but', 'also', 'to', 'collect.', 'are', 'you', 'gathering', 'people', 'or', 'a', 'bulk', 'of', 'leaves', 'in', 'your', 'garden', 'when', 'winter', 'is', 'coming?'], ['to', 'gather', 'friends', 'inside', 'your', 'place,', 'to', 'gather', 'information', 'for', 'the', 'police,', 'to', 'gather', 'food', 'for', 'the', 'homeless,', 'to', 'gather', 'objects', 'inside', 'your', 'bag,', 'to', 'gather', 'your', 'drunk', 'friend,', 'to', 'gather', 'a', 'molotof', 'cocktail', 'for', 'a', 'revolutionary', 'party'], ['it', 'is', 'the', 'opposite', 'of', 'dividing', 'because', 'the', 'basic', 'idea', 'is', 'that', 'you', 'have', 'a', 'lot', 'of', 'objects', 'far', 'away', 'from', 'each', 'other,', 'in', 'different', 'rooms,', 'in', 'different', 'building,', 'in', 'different', 'cities', 'and', 'you', 'want', 'to', 'have', 'all', 'of', 'them', 'on', 'your', 'bed', 'so', 'you', 'just', 'go', 'and', 'pick', 'them', 'up', 'from', 'where', 'they', 'are', 'you', 'put', 'them', 'in', 'a', 'bag', 'and', 'go', 'back', 'home'], ['my', 'favorite', 'activity', 'since', '200000000', 'years,', 'to', 'gather', 'food,', 'to', 'find', 'something', 'and', 'to', 'collect', 'it.', 'since', 'im', 'a', 'racoon', 'i', 'like', 'to', 'gather', 'things', 'around', 'from', 'the', 'street.', 'my', 'flatmate', 'is', 'desperate', 'about', 'it.', 'but', 'i', 'always', 'find', 'nice', 'things:', 'a', 'table,', 'a', 'confy', 'armchair,', 'some', 'baskets,', 'some', 'vases.']]\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from nltk.corpus import stopwords\n",
|
||||||
|
"sw = stopwords.words(\"english\")\n",
|
||||||
|
"from urllib.request import urlopen\n",
|
||||||
|
"import json\n",
|
||||||
|
"\n",
|
||||||
|
"resultSentences = []\n",
|
||||||
|
"labels_corpus = []\n",
|
||||||
|
"\n",
|
||||||
|
"url = f\"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image=think-classify7.jpg\"\n",
|
||||||
|
"response = urlopen(url)\n",
|
||||||
|
"data_json = json.loads(response.read()) \n",
|
||||||
|
"\n",
|
||||||
|
"labels = data_json['labels']\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"for label in labels:\n",
|
||||||
|
" sent = label['text'].split()\n",
|
||||||
|
" labels_corpus.append(sent)\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
"print(labels_corpus)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "387f722e-bb19-45cc-a0f9-8a1186febd56",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 199,
|
||||||
|
"id": "b3d40ae4-cfe8-4346-9d9f-23e2dbc50c0d",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"punctuation = ['.', ',', ';', '(', ')', ':']\n",
|
||||||
|
"\n",
|
||||||
|
"# since .split(' ') does not split a word from any punctuation, \n",
|
||||||
|
"# this function search for any string which last character (word[-1]]) is in the variable 'punctuation';\n",
|
||||||
|
"# if that is the case, the function will remove the last charachter, else it will leave it as it is.\n",
|
||||||
|
"def clean_word(word):\n",
|
||||||
|
" for character in word:\n",
|
||||||
|
" if word[-1] in punctuation:\n",
|
||||||
|
" return word[0:-1]\n",
|
||||||
|
" if word[0] in punctuation:\n",
|
||||||
|
" return word[1:]\n",
|
||||||
|
" else:\n",
|
||||||
|
" return word"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 200,
|
||||||
|
"id": "5c37d124-eaa8-4275-9556-473a966fdcb7",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# The arguments in this functions are 2 texts (text_a and text_b) an index for where the text_a starts and an index for where it ends.\n",
|
||||||
|
"def bridge(text_a, text_b, start_a, isLast):\n",
|
||||||
|
" \n",
|
||||||
|
" matchFound = 0\n",
|
||||||
|
" start_next = 0\n",
|
||||||
|
" \n",
|
||||||
|
" # for index i in text_a from a given index until the end of text_a\n",
|
||||||
|
" for i in range(start_a, len(text_a)):\n",
|
||||||
|
" if matchFound:\n",
|
||||||
|
" break\n",
|
||||||
|
" \n",
|
||||||
|
" # we name word_a the index i in text_a\n",
|
||||||
|
" word_a = text_a[i]\n",
|
||||||
|
" # if word_a is not in the given list of stopwords:\n",
|
||||||
|
" if word_a not in sw:\n",
|
||||||
|
" # for index j in the entire text_b:\n",
|
||||||
|
" for j in range(0, len(text_b)):\n",
|
||||||
|
" \n",
|
||||||
|
" # we name word_b the word with index j in text_b\n",
|
||||||
|
" word_b = text_b[j]\n",
|
||||||
|
" \n",
|
||||||
|
" # if word_a equals to word_b:\n",
|
||||||
|
" if clean_word(word_a) == clean_word(word_b):\n",
|
||||||
|
" \n",
|
||||||
|
" # resultSentences is a list to which the following informations will add up:\n",
|
||||||
|
" resultSentences.append({\n",
|
||||||
|
" 'text': text_a,\n",
|
||||||
|
" 'start': start_a,\n",
|
||||||
|
" 'end': i,\n",
|
||||||
|
" 'hasMatch': 1\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" # if the text in position text_a is the last text to be compared:\n",
|
||||||
|
" # the same informations as above will be added, except that there will be no index for its end.\n",
|
||||||
|
" if isLast:\n",
|
||||||
|
" resultSentences.append({\n",
|
||||||
|
" 'text': text_b,\n",
|
||||||
|
" 'start': j,\n",
|
||||||
|
" 'end': None,\n",
|
||||||
|
" 'hasMatch': 1\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" # after the match is found between the 2 texts, the function will break\n",
|
||||||
|
" matchFound = 1 \n",
|
||||||
|
" start_next = j\n",
|
||||||
|
" break\n",
|
||||||
|
" \n",
|
||||||
|
" if matchFound == 0:\n",
|
||||||
|
" resultSentences.append({\n",
|
||||||
|
" 'text': text_a,\n",
|
||||||
|
" 'start': start_a,\n",
|
||||||
|
" 'end': None,\n",
|
||||||
|
" 'hasMatch': 0\n",
|
||||||
|
" })\n",
|
||||||
|
" \n",
|
||||||
|
" if isLast:\n",
|
||||||
|
" resultSentences.append({\n",
|
||||||
|
" 'text': text_b,\n",
|
||||||
|
" 'start': 0,\n",
|
||||||
|
" 'end': None,\n",
|
||||||
|
" 'hasMatch': 0\n",
|
||||||
|
" })\n",
|
||||||
|
"\n",
|
||||||
|
" \n",
|
||||||
|
" # the function returns the index of the 'same word' in the text_b\n",
|
||||||
|
" return start_next"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 201,
|
||||||
|
"id": "d4862edf-c8cf-44dc-bd41-33549da33c0b",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def bridge_list(corpus):\n",
|
||||||
|
" start_a = 0\n",
|
||||||
|
" result = \"\"\n",
|
||||||
|
" \n",
|
||||||
|
" #for all texts indexes within the corpus to be compared:\n",
|
||||||
|
" for text_index in range(0, len(corpus)-1):\n",
|
||||||
|
"\n",
|
||||||
|
" # the last text_a to be compared has to be the text indexed as corpus[-2];\n",
|
||||||
|
" # the last text_b will then be the last text of the corpus (corpus[-1]).\n",
|
||||||
|
" isLast = text_index == len(corpus)-2\n",
|
||||||
|
" # text_a is a given index of the corpus and text_b is the following index\n",
|
||||||
|
" text_a = corpus[text_index]\n",
|
||||||
|
" text_b = corpus[text_index + 1]\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" #start_a is the index (in text_b) of the first 'common word' between text_a and text_b;\n",
|
||||||
|
" #start_a is the starting point to compare a text and its following (in index order within the corpus); \n",
|
||||||
|
"\n",
|
||||||
|
" start_next = bridge(text_a, text_b, start_a, isLast)\n",
|
||||||
|
" start_a = start_next\n",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 202,
|
||||||
|
"id": "4363e385-7772-422b-b7b5-7f425e79878d",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"def render_sentence(sentence, highlightNext):\n",
|
||||||
|
" result = ''\n",
|
||||||
|
" start = 0\n",
|
||||||
|
" end = len(sentence['text'])\n",
|
||||||
|
" if(sentence['start']):\n",
|
||||||
|
" start = sentence['start']\n",
|
||||||
|
" if(sentence['end']):\n",
|
||||||
|
" end = sentence['end']\n",
|
||||||
|
" \n",
|
||||||
|
" text = sentence['text']\n",
|
||||||
|
" \n",
|
||||||
|
" highlight = highlightNext\n",
|
||||||
|
" \n",
|
||||||
|
" for index in range(start, end):\n",
|
||||||
|
" word = text[index]\n",
|
||||||
|
" \n",
|
||||||
|
" if(highlight == 1):\n",
|
||||||
|
" result = result + '<span class=\"highlighit\">' + word + '</span>'\n",
|
||||||
|
" highlight = 0;\n",
|
||||||
|
" continue\n",
|
||||||
|
" else:\n",
|
||||||
|
" if index == end -1 and sentence['hasMatch']:\n",
|
||||||
|
" highlight = 1\n",
|
||||||
|
"\n",
|
||||||
|
" result = result + \" \" + word\n",
|
||||||
|
" \n",
|
||||||
|
" return result, highlight\n",
|
||||||
|
" \n",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 203,
|
||||||
|
"id": "d30e2363-37e7-4437-af7a-572eb56d9266",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
" to meet, but also to collect. are you gathering people or a bulk of leaves in your garden when winter is coming? to gather friends inside your place, to gather information for the police, to gather food for the homeless, to gather <span class=\"highlighit\">objects</span> far away from each other, in different rooms, in different building, in different cities and you want to have all of them on your bed so you just go and pick them up from where they are you put them in a bag and go back home my favorite activity since 200000000 years, to gather food, to find something and to collect it. since im a racoon i like to gather things around from the street. my flatmate is desperate about it. but i always find nice things: a table, a confy armchair, some baskets, some vases.\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"bridge_list(labels_corpus)\n",
|
||||||
|
"\n",
|
||||||
|
"endResult = ''\n",
|
||||||
|
"\n",
|
||||||
|
"highlightNext = 0\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(0, len(resultSentences)):\n",
|
||||||
|
" sentence = resultSentences[i]\n",
|
||||||
|
" start = sentence['start']\n",
|
||||||
|
" end = sentence['end']\n",
|
||||||
|
" sentenceText = sentence['text']\n",
|
||||||
|
" \n",
|
||||||
|
" sentence, highlight = render_sentence(sentence, highlightNext)\n",
|
||||||
|
" highlightNext = highlight\n",
|
||||||
|
" \n",
|
||||||
|
" endResult = endResult + \" \" + sentence\n",
|
||||||
|
"\n",
|
||||||
|
"print(endResult)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "e5e13d80-deef-423d-82f7-be71e69ee902",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "3014a45f-d18f-4fef-b683-45eb50abed03",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "1602a233-c977-4e8c-87f4-133f0792d181",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,172 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "66f72396-0cf1-41cf-a486-2930d2ad1652",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# individual_map\n",
|
||||||
|
"give a string with the name of the image-file that was annotated with the Annotation Compass; Select one or more specific targets and return a list of all labels that include these targetsselect one or more specific users and return a list of all labels from these users."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "de97fe2f-daae-4293-a0b3-ea42c759535a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from urllib.request import urlopen\n",
|
||||||
|
"import json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "9bd8860a-9967-49d5-a74a-b5de669dfe6d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def individual_map(image: str, users: list ) -> list:\n",
|
||||||
|
" \n",
|
||||||
|
" \"\"\"give a string with the name of the image-file that was annotated with the Annotation Compass; Select one or more specific targets and return a list of all labels that include these targetsselect one or more specific users and return a list of all labels from these users.\"\"\" \n",
|
||||||
|
"\n",
|
||||||
|
" url = f\"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image={image}\"\n",
|
||||||
|
" response = urlopen(url)\n",
|
||||||
|
" data_json = json.loads(response.read()) \n",
|
||||||
|
" \n",
|
||||||
|
" filtered_map = []\n",
|
||||||
|
" for label in data_json['labels']:\n",
|
||||||
|
" for user in users:\n",
|
||||||
|
" if label['userID'] == user:\n",
|
||||||
|
" filtered_map.append(label)\n",
|
||||||
|
" return filtered_map"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "1094ed8e-1387-481e-b612-9a8cc81d5c18",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This function was built for a project where individuals are invited to add their annotations on a map using the Annotation Compass. Each annotation-label is stored in a json-file and includes the annotation-text itself, but also the name of the image-file as well as the position, size, index, timestamp and userID of the annotation.\n",
|
||||||
|
"\n",
|
||||||
|
" Example for a label:\n",
|
||||||
|
"\n",
|
||||||
|
" {'image': 'map.jpg',\n",
|
||||||
|
" 'position': {'x': 12, 'y': 97},\n",
|
||||||
|
" 'size': {'width': 43, 'height': 18},\n",
|
||||||
|
" 'text': 'This is a text! Is this a text?',\n",
|
||||||
|
" 'timestamp': 'Wed, 01 Dec 2021 14:04:00 GMT',\n",
|
||||||
|
" 'userID': 5766039063}\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"If interested in all annotations of one or more specific users, individual_map() can help. The function needs a string with the name of the of the image-file that was annotated with the annotation compass tool as well as one or more specific userIDs to target. The output is a list of all labels from the users of interest.\n",
|
||||||
|
"\n",
|
||||||
|
"How to get a json-file with annotation-labels?\n",
|
||||||
|
"\n",
|
||||||
|
" https://hub.xpub.nl/soupboat/generic-labels/\n",
|
||||||
|
"The Annotation Compass allows people to uplaod an image and ask others to annotate it. A json-file of the annotations is provided."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2c3e992a-317b-4433-8c3b-9efcedea575d",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Examples\n",
|
||||||
|
"\n",
|
||||||
|
"In this example, the function returns all annotation-labels of two specific users."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "e3d7e97b-0089-4c29-a2c1-9ef823ff2e37",
|
||||||
|
"metadata": {
|
||||||
|
"scrolled": true,
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[{'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 63.9896, 'y': 34.2958},\n",
|
||||||
|
" 'size': {'height': 3.23944, 'width': 2.90155},\n",
|
||||||
|
" 'text': 'here, someone called my behaviour \"strange\"',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:36:04 GMT',\n",
|
||||||
|
" 'userID': '8112114057'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 39.3264, 'y': 46.831},\n",
|
||||||
|
" 'size': {'height': 6.19718, 'width': 9.2228},\n",
|
||||||
|
" 'text': 'here, someone screamed at me \"move fucking chinee\"',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:36:55 GMT',\n",
|
||||||
|
" 'userID': '8112114057'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 36.5285, 'y': 54.2958},\n",
|
||||||
|
" 'size': {'height': 1.69014, 'width': 3.31606},\n",
|
||||||
|
" 'text': 'here, someone screamed at me, right into my face, something I could not understand',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:37:37 GMT',\n",
|
||||||
|
" 'userID': '8112114057'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 42.5389, 'y': 45.7042},\n",
|
||||||
|
" 'size': {'height': 13.662, 'width': 23.9378},\n",
|
||||||
|
" 'text': 'here, someone told me to move away',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:38:04 GMT',\n",
|
||||||
|
" 'userID': '8112114057'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 39.1192, 'y': 36.2676},\n",
|
||||||
|
" 'size': {'height': 11.6901, 'width': 20.4145},\n",
|
||||||
|
" 'text': 'here, someone told to stop looking at them',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:38:45 GMT',\n",
|
||||||
|
" 'userID': '8112114057'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 46.3713, 'y': 58.4289},\n",
|
||||||
|
" 'size': {'height': 6.99541, 'width': 15.1055},\n",
|
||||||
|
" 'text': 'somewhere between this line i lost my ID card. and I really wasnt aware that this could linger a lot my registration to the municipality. This kinda triggered but feeling for me, as I felt a lot disorented here, having no formal document verifying who I am and feeling guilty tat I am still not registered.',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:40:54 GMT',\n",
|
||||||
|
" 'userID': '6004575665'}]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"individual_map('rejection_map.jpg', ['8112114057', '6004575665'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "fcbbb728-217d-47a3-b672-d03d120fa408",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,258 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b774afd4-4a80-48c5-a09a-7623429c7f0a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Mashup()\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "626002a1-958c-4a31-bf75-50cd5dfab433",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**Mashup()** is a function that compare **two similar texts** and produce **a third text** that randomly choose between the original texts. \n",
|
||||||
|
"The outcome is a text with the differences chosen through random choice.\n",
|
||||||
|
"\n",
|
||||||
|
"A function that: \n",
|
||||||
|
"1. takes into account **2 similar texts** (example: 2 different translations of a poems)\n",
|
||||||
|
"2. finds the **fixed_words** and uses them as the fixed text for the new piece of text\n",
|
||||||
|
"3. puts the results together into **a new piece**, randomly choosing the different options \n",
|
||||||
|
"4. html output that **highlights the different random choices** of the translations\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b3e00ed0-59e2-4e1c-aa23-fd412fc8524b",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**how to use**: to use this function it is necessary to have two texts with the same number of lines (as it goes throught the two texts and compares them line by line). It can be use also with list of strings."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "04e48da5-eeae-440d-8f8a-5952d6706d81",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**input:** 2 texts that are similar but not the exact copy of each other -- "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "e8b2ab5c-3b41-4dce-8490-8d7052cdb858",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"**output:** a new text that showcase the differences // a new text made out of random choice // *still not clear yet* // extracted pdf/txt file?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "e6d5f744-d079-4a51-a5c2-6845a7a7ac56",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# define texts\n",
|
||||||
|
"\n",
|
||||||
|
"text1= '''\n",
|
||||||
|
"The glasses were empty\n",
|
||||||
|
"The bottle was shattered\n",
|
||||||
|
"The bed was wide open\n",
|
||||||
|
"The door was tight shuttered\n",
|
||||||
|
"Each shard was a star\n",
|
||||||
|
"Of bliss and of beauty\n",
|
||||||
|
"That flashed on the floor\n",
|
||||||
|
"All dusty and dirty\n",
|
||||||
|
"And I was dead drunk\n",
|
||||||
|
"Lit up wildly ablaze\n",
|
||||||
|
"You were drunk and alive\n",
|
||||||
|
"In a naked embrace!\n",
|
||||||
|
"'''\n",
|
||||||
|
"text2= '''\n",
|
||||||
|
"So the glasses were empty\n",
|
||||||
|
"and the bottle broken\n",
|
||||||
|
"And the bed was wide open\n",
|
||||||
|
"and the door closed\n",
|
||||||
|
"And all of the glass stars\n",
|
||||||
|
"of happiness and beauty \n",
|
||||||
|
"were sparkling in the dust\n",
|
||||||
|
"of the poorly dusted room.\n",
|
||||||
|
"And I was dead drunk\n",
|
||||||
|
"And I was a bonfire\n",
|
||||||
|
"And you were alive, drunk,\n",
|
||||||
|
"all naked in my arms.\n",
|
||||||
|
"'''\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "a8f10c45-0ce7-4ef8-9a5f-6a92f69902a2",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "3c62af9c-b078-4117-b84b-e191048c6a93",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import difflib\n",
|
||||||
|
"from random import choice\n",
|
||||||
|
"\n",
|
||||||
|
"def mashup(text1,text2): #take into account 2 texts\n",
|
||||||
|
" \n",
|
||||||
|
" text1 = text1.splitlines() #split texts in lines\n",
|
||||||
|
" text2 = text2.splitlines()\n",
|
||||||
|
" \n",
|
||||||
|
" fixed_words= [] #define empty list for fixed_words (words that are the same in both texts) // a list of lists of words\n",
|
||||||
|
" for line_A, line_B in zip(text1, text2): #start the first loop reading line by line from both texts at the same time (=zip)\n",
|
||||||
|
" words_A = line_A.split() #split lines in lists of words\n",
|
||||||
|
" words_B = line_B.split()\n",
|
||||||
|
" \n",
|
||||||
|
" d = difflib.Differ() #Differ compare sequences of lines of text, and produce human-readable differences ('+' in text1), ('-' in text2), ('' fixed_Words)\n",
|
||||||
|
" diff = d.compare(words_A, words_B) #compare the difference between the two lists of words\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" linelist = [] #define empty list \n",
|
||||||
|
" for result in diff: #second loop that goes through all the lines and then the words of both texts simultaneously\n",
|
||||||
|
" code, word = result.split(' ', 1) #split result of diff in code [('+'), ('-') or ('')] and the resulting word (is it the same or is it just in one of the two texts?)\n",
|
||||||
|
" word = word.strip() #to be sure it doesn't have any weird things /n at the ends of the lines\n",
|
||||||
|
" if code == '' : #if the code is ' ' (nothing) it means that the word can be found in both texts\n",
|
||||||
|
" linelist.append(word) #if this happens, put the corresponding words in the linelist\n",
|
||||||
|
" fixed_words.append(linelist) #afterwards, add linelist to fixed_words (linelist is inside the loop so all the words in every line are put in there, but fixed_words is outside so that just the words are added just once)\n",
|
||||||
|
" \n",
|
||||||
|
" length = len(text1) #define lenght of text1\n",
|
||||||
|
" for linenumber in range(length): #for the number of the lines in the lenght of the text\n",
|
||||||
|
" cut_left1 = 0 #the beginning of both texts is position n°0 (on the left side of the lines)\n",
|
||||||
|
" cut_left2 = 0\n",
|
||||||
|
" words_1 = text1[linenumber].split() #words_1 is split in words keeping the position in the lines\n",
|
||||||
|
" words_2 = text2[linenumber].split() \n",
|
||||||
|
" if len(fixed_words[linenumber]) > 0: #if the index on the fixed words in the line is more than 0 (it's not the first one)\n",
|
||||||
|
" for fixed_word in fixed_words[linenumber]: #for all the fixed_words that are in the fixed_words list always following the linenumbers\n",
|
||||||
|
" cut_right1 = words_1.index(fixed_word) #finding the first fixed_word from the left (beginning / position 0) to the right(end of sentence / last word in the line)\n",
|
||||||
|
" cut_right2 = words_2.index(fixed_word) #in both texts\n",
|
||||||
|
"\n",
|
||||||
|
" slice_1 = words_1[cut_left1 : cut_right1] #create slice_1 \n",
|
||||||
|
" slice_2 = words_2[cut_left2 : cut_right2]\n",
|
||||||
|
" print(choice([slice_1, slice_2]))\n",
|
||||||
|
" \n",
|
||||||
|
" cut_left1 = cut_right1 #now invert, when it's gone through all the words till finding the last fixed word\n",
|
||||||
|
" cut_left2 = cut_right2\n",
|
||||||
|
"\n",
|
||||||
|
" slice_1 = words_1[cut_left1 :] #from the last fixed_word found to the right\n",
|
||||||
|
" slice_2 = words_2[cut_left2 :]\n",
|
||||||
|
" print(choice([slice_1, slice_2])) #choose\n",
|
||||||
|
" else:\n",
|
||||||
|
" slice_1 = words_1[cut_left1 :] #here is doing it outside of the loop ( it gets the last word of the line if it's not a\n",
|
||||||
|
" slice_2 = words_2[cut_left2 :]\n",
|
||||||
|
" print(choice([slice_1, slice_2])) #choose\n",
|
||||||
|
" print('--------') \n",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "78c7643c-e797-451e-872d-e6dd81f0052c",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"[]\n",
|
||||||
|
"--------\n",
|
||||||
|
"['So', 'the']\n",
|
||||||
|
"['glasses']\n",
|
||||||
|
"['were']\n",
|
||||||
|
"['empty']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['and', 'the']\n",
|
||||||
|
"['bottle', 'was', 'shattered']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['The']\n",
|
||||||
|
"['bed']\n",
|
||||||
|
"['was']\n",
|
||||||
|
"['wide']\n",
|
||||||
|
"['open']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['and', 'the']\n",
|
||||||
|
"['door', 'was', 'tight', 'shuttered']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['And', 'all', 'of', 'the', 'glass', 'stars']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['of', 'happiness']\n",
|
||||||
|
"['and']\n",
|
||||||
|
"['beauty']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['were', 'sparkling', 'in']\n",
|
||||||
|
"['the', 'dust']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['All', 'dusty', 'and', 'dirty']\n",
|
||||||
|
"--------\n",
|
||||||
|
"[]\n",
|
||||||
|
"['And']\n",
|
||||||
|
"['I']\n",
|
||||||
|
"['was']\n",
|
||||||
|
"['dead']\n",
|
||||||
|
"['drunk']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['And', 'I', 'was', 'a', 'bonfire']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['And', 'you']\n",
|
||||||
|
"['were', 'alive,', 'drunk,']\n",
|
||||||
|
"--------\n",
|
||||||
|
"['In', 'a']\n",
|
||||||
|
"['naked', 'in', 'my', 'arms.']\n",
|
||||||
|
"--------\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"mashup(text1,text2)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "07f2e386-3380-4dc0-b680-d5b1288e7794",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "0b127fbb-6e70-4614-a727-2ec476e43236",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "66f72396-0cf1-41cf-a486-2930d2ad1652",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Repeat\n",
|
||||||
|
"Repeat a string for a specified number of times"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "9bd8860a-9967-49d5-a74a-b5de669dfe6d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def repeat(text: str, times: int = 2) -> str:\n",
|
||||||
|
" \"\"\"Repeat a string for a specified number of times\"\"\"\n",
|
||||||
|
" return text * times"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d50511cb-a810-4fe1-a681-e5cb1392c0d0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"![ara repeating itself](https://www.dienst.nl/sub/upload/images/1/30019_550.jpg)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "1094ed8e-1387-481e-b612-9a8cc81d5c18",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This function has many attractive qualities, but its ability to repeat human speech is one that makes it truly unique among other types of companion python functions and one that has ensured its popularity for generations. You are likely to find, though, that the function's talents for mimicry still pales in comparison to the fact that it is charming, engaging, and truly remarkable. Here is one of the most popular repeating function so that you can appreciate more about what it has to offer. It often says injuries to people and computers. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2c3e992a-317b-4433-8c3b-9efcedea575d",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Examples\n",
|
||||||
|
"\n",
|
||||||
|
"The function takes a string as a parameter, and by default it repeats it twice. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "e3d7e97b-0089-4c29-a2c1-9ef823ff2e37",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'hellohello'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"repeat('hello')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d3ce6961-68ff-4338-a71f-f8d77aa4f949",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Eventually with a second parameter you can specify how many times you want it to repeats. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "dd3f3a0b-3145-4914-8638-951bcdbd0774",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'salutsalutsalutsalut'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"repeat('salut', 4)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "4b1d288c-50c0-4da2-9ea9-bf5adb06b034",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Respell\n",
|
||||||
|
"Respell receives as input a text as a string type, and substitute all the occurrences of a targeted word with a replacement as a string type chosen by the user."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "691152f6-8e85-4fc2-8c98-848448ee959a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from nltk.tokenize import word_tokenize"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "2a46fe37-b62f-482a-a040-9f7a5d39fc0e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# text, target, and replacement are string types\n",
|
||||||
|
"def respell(text, target, replacement):\n",
|
||||||
|
" target = target.lower()\n",
|
||||||
|
" txt = word_tokenize(text)\n",
|
||||||
|
" new = []\n",
|
||||||
|
" \n",
|
||||||
|
" for w in txt:\n",
|
||||||
|
" if w == target:\n",
|
||||||
|
" w = replacement\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" elif w == target[0:1].upper() + target[1:]:\n",
|
||||||
|
" w = replacement[0:1].upper() + replacement[1:] \n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" elif w == target.upper():\n",
|
||||||
|
" w = replacement.upper()\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" else:\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" text = ' '.join(new)\n",
|
||||||
|
" final= text.replace(' .','.').replace(' ,',',').replace(' :',':').replace(' ;',';').replace('< ','<').replace(' >','>').replace(' / ','/').replace('& ','&')\n",
|
||||||
|
" return final"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "63374a00-6091-484d-9ffd-ebf79d13cdc1",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This function in itself could be understood as a filter to process and alter texts. By targeting specific words and replacing them, either for another word, for specific characters or for blank spaces, the user of the tool can intervene inside a text. One could break down the meaning of a text or create new narrative meanings by exposing its structure, taking out or highlighting specific and meaningful words and detaching such text from its original context. \n",
|
||||||
|
"This tool offers a broad spectrum of possibilities in which it can be used, from a very political and subversive use, to a more playful and poetic one."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "1fde0e28-f253-4992-96d1-0497da2959f6",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Examples"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "6c80de23-d4ad-45a7-8b2f-b07c4ff2e549",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'potato is potato'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"respell(\"life is life\",\"life\",\"potato\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "772ae978-5551-486e-add1-0a5a660a0bff",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'🥙 is 🥙'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"respell(\"life is life\",\"life\",\"🥙\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,189 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "f0e7e936-865b-4389-b180-e07eaf8f4cfc",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Reveal\n",
|
||||||
|
"Reveal takes a text as string input and deletes all its characters except the input list of words."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "f920735b-ed2a-4dd6-8c28-95b4dafad70a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from nltk.tokenize import word_tokenize"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"id": "2c72ec84-7f91-4d1e-b9f9-6629ab4fae94",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def reveal(text,group):\n",
|
||||||
|
" txt = word_tokenize(text)\n",
|
||||||
|
" \n",
|
||||||
|
" txt_linebr = []\n",
|
||||||
|
" for token in txt:\n",
|
||||||
|
" if token == '<':\n",
|
||||||
|
" continue\n",
|
||||||
|
" elif token == 'br/':\n",
|
||||||
|
" token='<br/>'\n",
|
||||||
|
" txt_linebr.append(token)\n",
|
||||||
|
" elif token == '>':\n",
|
||||||
|
" continue\n",
|
||||||
|
" else:\n",
|
||||||
|
" txt_linebr.append(token) \n",
|
||||||
|
" new = []\n",
|
||||||
|
" for w in txt_linebr:\n",
|
||||||
|
" if w=='<br/>':\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" elif w not in group:\n",
|
||||||
|
" w = len(w) * ' '\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" elif w in group :\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" text = ' '.join(new)\n",
|
||||||
|
" final= text.replace(' .','.').replace(' ,',',').replace(' :',':').replace(' ;',';').replace('< ','<').replace(' >','>').replace(' / ','/').replace('& ','&')\n",
|
||||||
|
" return final"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "cff36759-e377-48d5-93f8-d78f6f9a3050",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This function in itself could be understood as a filter to process and alter texts. By chosing to keeping specific words of a text and deleting all the others, the user of the tool can intervene inside a text. One could break down the meaning of a text or create new narrative meanings by exposing its structure, taking out or highlighting specific and meaningful words and detaching such text from its original context. \n",
|
||||||
|
"This tool offers a broad spectrum of possibilities in which it can be used, from a very political and subversive use, to a more playful and poetic one."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"id": "a6bce73e-8084-4bd0-b7b8-95cd39069030",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"text = f\"\"\"\n",
|
||||||
|
"Live\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"Live\n",
|
||||||
|
"Live\n",
|
||||||
|
"\n",
|
||||||
|
"When we all give the power\n",
|
||||||
|
"We all give the best\n",
|
||||||
|
"Every minute of an hour\n",
|
||||||
|
"Don't think about a rest\n",
|
||||||
|
"Then you all get the power\n",
|
||||||
|
"You all get the best\n",
|
||||||
|
"When everyone gives everything\n",
|
||||||
|
"And every song everybody sings\n",
|
||||||
|
"\n",
|
||||||
|
"Then it's live\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"Live\n",
|
||||||
|
"\n",
|
||||||
|
"Live is life, when we all feel the power\n",
|
||||||
|
"Live is life, come on stand up and dance\n",
|
||||||
|
"Live is life, when the feeling of the people\n",
|
||||||
|
"Live is life, is the feeling of the band\n",
|
||||||
|
"\n",
|
||||||
|
"When we all give the power\n",
|
||||||
|
"We all give the best\n",
|
||||||
|
"Every minute of an hour\n",
|
||||||
|
"Don't think about a rest\n",
|
||||||
|
"Then you all get the power\n",
|
||||||
|
"You all get the best\n",
|
||||||
|
"When everyone gives everything\n",
|
||||||
|
"And every song everybody sings\n",
|
||||||
|
"\n",
|
||||||
|
"Then it's live\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"Live\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"Live\n",
|
||||||
|
"\n",
|
||||||
|
"Live\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"Live\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"\n",
|
||||||
|
"And you call when it's over\n",
|
||||||
|
"You call it should last\n",
|
||||||
|
"Every minute of the future\n",
|
||||||
|
"Is a memory of the past\n",
|
||||||
|
"'Cause we all gave the power\n",
|
||||||
|
"We all gave the best\n",
|
||||||
|
"And everyone gave everything\n",
|
||||||
|
"And every song everybody sang\n",
|
||||||
|
"Live is life\n",
|
||||||
|
"\"\"\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "8d6dfda4-122b-42cc-8d29-5d141d726c47",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Examples"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 16,
|
||||||
|
"id": "89d83728-6e1c-4270-b0bc-6cfb59f4f389",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'Live Live is life Live Live live Live is life Live is life Live Live is life Live is life Live is life Live is life is live Live is life Live Live is life Live Live Live is life Live Live is life Live is life'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 16,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"reveal(text,[\"Live\",\"is\",\"life\",\"live\"])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "8ec2e799-7e05-42c3-ae4c-84a299b66a2d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "5688f740-c1a2-4271-880d-2be65c748d94",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# REVERSE!"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "df889e4f-3ccc-4411-b4c7-53c8098661c9",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from textblob import TextBlob\n",
|
||||||
|
"\n",
|
||||||
|
"def reverse (inputz: str) -> str:\n",
|
||||||
|
" \"\"\"Reverse the input sentence by sentence\"\"\"\n",
|
||||||
|
" blob = TextBlob(inputz)\n",
|
||||||
|
" return \"\\n\".join(str(reversed(blob.sentences)))\n",
|
||||||
|
" \n",
|
||||||
|
" # return \" \".join(reversed(inputz.split()))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"id": "c481d133-0fc4-4046-8f50-0e5cea1c0e11",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'<\\nl\\ni\\ns\\nt\\n_\\nr\\ne\\nv\\ne\\nr\\ns\\ne\\ni\\nt\\ne\\nr\\na\\nt\\no\\nr\\n \\no\\nb\\nj\\ne\\nc\\nt\\n \\na\\nt\\n \\n0\\nx\\na\\nc\\n4\\na\\nf\\n3\\n9\\n0\\n>'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 8,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"reverse(\"hello world\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "66f72396-0cf1-41cf-a486-2930d2ad1652",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Shout\n",
|
||||||
|
"This function take a text and shouts it LOUD. It repeats the vowels for a specified number of times."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "9bd8860a-9967-49d5-a74a-b5de669dfe6d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def shout(text: str, volume: int = 5) -> str:\n",
|
||||||
|
" \"\"\"Repeat the vowels in a string for a specified number of times\"\"\"\n",
|
||||||
|
" shouted_text = ''\n",
|
||||||
|
" for c in text:\n",
|
||||||
|
" character = c\n",
|
||||||
|
" if c.lower() in ['a','e','i','o','u','y']:\n",
|
||||||
|
" character = character * volume\n",
|
||||||
|
" shouted_text = shouted_text + character\n",
|
||||||
|
" return shouted_text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d50511cb-a810-4fe1-a681-e5cb1392c0d0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"![Snake on a sbake](https://hub.xpub.nl/soupboat/~kamo/assets/goose.jpg)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2c3e992a-317b-4433-8c3b-9efcedea575d",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Examples"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "e3d7e97b-0089-4c29-a2c1-9ef823ff2e37",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'heeeeelp'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"shout('help')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d3ce6961-68ff-4338-a71f-f8d77aa4f949",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"The first parameter is the text you want to shout. It can be anything, like a terrorized cry or a drunk song at 4am outside the pub. \n",
|
||||||
|
"If you want to scream louder you can specify a second parameter for the volume. This is a number and by default is 5. It has to be positive but there are no limits to it."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "dd3f3a0b-3145-4914-8638-951bcdbd0774",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'HEEEEEEEEEELP'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"shout('HELP', 10)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d7e70281-0562-4fb0-8c07-b2ea7143b393",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"You see, this is very a dangerous situation."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "9f685cab-278e-4b44-afd9-6e6012981442",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'MG HLP'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"shout('OMG HELP', 0)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "0f668b5e-43bf-4321-b05b-5930d6eac152",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"A muted scream"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "af317257-97a8-46db-ac92-e06bdef22ed3",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Stitch\n",
|
||||||
|
"Stitch receives as input a text as a string type, and replaces all the occurrences of a target word, with a character or a word that is repeated as many times as the length of the target. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "8c280e90-22dc-4e59-90fe-3bdf97da06b2",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from nltk.tokenize import word_tokenize"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "f26e528c-1d61-4796-a42a-a3d5d0edc574",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# text, target, and replacement are string types\n",
|
||||||
|
"def stich(text, target, replacement):\n",
|
||||||
|
" target = target.lower()\n",
|
||||||
|
" txt = word_tokenize(text)\n",
|
||||||
|
" new = []\n",
|
||||||
|
" \n",
|
||||||
|
" for w in txt:\n",
|
||||||
|
" if w == target:\n",
|
||||||
|
" w = len(w)*replacement\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" elif w == target[0].upper() + target[1:]:\n",
|
||||||
|
" w = len(w)*replacement\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" elif w== target.upper():\n",
|
||||||
|
" w = len(w)*replacement \n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" else:\n",
|
||||||
|
" new = new + [w]\n",
|
||||||
|
" text = ' '.join(new)\n",
|
||||||
|
" final= text.replace(' .','.').replace(' ,',',').replace(' :',':').replace(' ;',';').replace('< ','<').replace(' >','>').replace(' / ','/').replace('& ','&')\n",
|
||||||
|
" return final"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "7e5443c5-e6d3-4dca-b196-7f8c0204814f",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This function in itself could be understood as a filter to process and alter texts. By targeting specific words and stitching them, with a character or a word that is repeated as many times as the length of the target , the user of the tool can intervene inside a text. One could break down the meaning of a text or create new narrative meanings by exposing its structure, taking out or highlighting specific and meaningful words and detaching such text from its original context. \n",
|
||||||
|
"This tool offers a broad spectrum of possibilities in which it can be used, from a very political and subversive use, to a more playful and poetic one."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "e054e805-9abb-4751-af1f-0039975520d6",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Examples"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "32c73229-7914-4b16-8054-a74a6869ede8",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"' is '"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"stich(\"life is life\",\"life\",\" \")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "9d273092-5cda-4d75-ad1c-9473bf65e69a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'**** is ****'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"stich(\"life is life\",\"life\",\"*\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "b0805582-fa73-43b5-b6f9-01cfedd4003d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,190 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "66f72396-0cf1-41cf-a486-2930d2ad1652",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# target_map\n",
|
||||||
|
"Give a string with the name of the image-file that was annotated with the Annotation Compass; Select one or more specific targets and return a list of all labels that include these targets"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "dc7040fd-ec5d-49e6-98e5-1feae91fc74b",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from urllib.request import urlopen\n",
|
||||||
|
"import json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "9bd8860a-9967-49d5-a74a-b5de669dfe6d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def target_map(image: str, targets: list ) -> list:\n",
|
||||||
|
" \n",
|
||||||
|
" \"\"\"Give a string with the name of the image-file that was annotated with the Annotation Compass; Select one or more specific targets and return a list of all labels that include these targets.\"\"\" \n",
|
||||||
|
"\n",
|
||||||
|
" url = f\"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image={image}\"\n",
|
||||||
|
" response = urlopen(url)\n",
|
||||||
|
" data_json = json.loads(response.read()) \n",
|
||||||
|
" \n",
|
||||||
|
" filter_map = []\n",
|
||||||
|
" for label in data_json['labels']:\n",
|
||||||
|
" for target in targets:\n",
|
||||||
|
" if target in label['text']:\n",
|
||||||
|
" filter_map.append(label)\n",
|
||||||
|
" return filter_map"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "1094ed8e-1387-481e-b612-9a8cc81d5c18",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"This function was built for a project where individuals are invited to add their annotations on a map using the Annotation Compass. Each annotation-label is stored in a json-file and includes the annotation-text itself, but also the name of the image-file as well as the position, size, index, timestamp and userID of the annotation.\n",
|
||||||
|
"\n",
|
||||||
|
" Example for a label:\n",
|
||||||
|
"\n",
|
||||||
|
" {'image': 'map.jpg',\n",
|
||||||
|
" 'position': {'x': 12, 'y': 97},\n",
|
||||||
|
" 'size': {'width': 43, 'height': 18},\n",
|
||||||
|
" 'text': 'This is a text! Is this a text?',\n",
|
||||||
|
" 'timestamp': 'Wed, 01 Dec 2021 14:04:00 GMT',\n",
|
||||||
|
" 'userID': 5766039063}\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"If interested in all annotations that include one or more specific targets, target_map() can help. The function needs a string with the name of the of the image-file that was annotated with the annotation compass tool as well as one or more specific targets. The output is a list of all labels that include these targets.\n",
|
||||||
|
"\n",
|
||||||
|
"How to get a json-file with annotation-labels?\n",
|
||||||
|
"\n",
|
||||||
|
" https://hub.xpub.nl/soupboat/generic-labels/\n",
|
||||||
|
"The Annotation Compass allows people to uplaod an image and ask others to annotate it. A json-file of the annotations is provided."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2c3e992a-317b-4433-8c3b-9efcedea575d",
|
||||||
|
"metadata": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": [
|
||||||
|
"## Examples\n",
|
||||||
|
"\n",
|
||||||
|
"In this example, the function returns all annotation-labels that include two specific targets."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "e3d7e97b-0089-4c29-a2c1-9ef823ff2e37",
|
||||||
|
"metadata": {
|
||||||
|
"scrolled": true,
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[{'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 48.135, 'y': 20.4458},\n",
|
||||||
|
" 'size': {'height': 4.62487, 'width': 2.94785},\n",
|
||||||
|
" 'text': 'house viewing 2: meeting with some girls in the evening to see a room; felt super exposed and awkward. Later on, they rejected me.',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:36:48 GMT',\n",
|
||||||
|
" 'userID': '1933684842'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 76.25, 'y': 69.5246},\n",
|
||||||
|
" 'size': {'height': 12.3939, 'width': 15.625},\n",
|
||||||
|
" 'text': \"I once went to view a house here but it didn't have the floor. crap.\",\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:36:51 GMT',\n",
|
||||||
|
" 'userID': '6286616941'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 55.0889, 'y': 15.6154},\n",
|
||||||
|
" 'size': {'height': 4.21377, 'width': 3.55253},\n",
|
||||||
|
" 'text': \"the most unpleasant house viewing: my viewing overlapped with the previous person and I didn't got the chance to connect with the ones living them. How could then they know who I am and even consider me for the room?\",\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:37:46 GMT',\n",
|
||||||
|
" 'userID': '1933684842'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 45.2507, 'y': 29.3907},\n",
|
||||||
|
" 'size': {'height': 6.09319, 'width': 6.59631},\n",
|
||||||
|
" 'text': \"I had the most awkward house viewing here. The people barely talked to me and really let me know that they didn't like me. Obviously, I did not get the room.\",\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:38:09 GMT',\n",
|
||||||
|
" 'userID': '4287159985'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 42.0882, 'y': 18.8014},\n",
|
||||||
|
" 'size': {'height': 3.08325, 'width': 1.66289},\n",
|
||||||
|
" 'text': 'my first house viewing: I was really hopeful about this one, actually, because I felt a connection with the girl. I waited 2 weeks to be rejected from this one.',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:38:41 GMT',\n",
|
||||||
|
" 'userID': '1933684842'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 43.7995, 'y': 27.0609},\n",
|
||||||
|
" 'size': {'height': 9.319, 'width': 8.04749},\n",
|
||||||
|
" 'text': \"I had the most awkward house viewing here. The people barely talked to me and really let me know that they didn't like me. Not surprisingly, I did not get the room.\",\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:39:12 GMT',\n",
|
||||||
|
" 'userID': '1165348288'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 55.621, 'y': 33.6313},\n",
|
||||||
|
" 'size': {'height': 15.6597, 'width': 7.43427},\n",
|
||||||
|
" 'text': 'we were going to a friends house when we got trapped into the riot against covid restrictions and a car got on fire and it was super bad to see all the anger all these people had i felt small and sad and i just wanted to run as faster as i could',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:43:45 GMT',\n",
|
||||||
|
" 'userID': '4164927552'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 55.621, 'y': 33.6313},\n",
|
||||||
|
" 'size': {'height': 15.6597, 'width': 7.43427},\n",
|
||||||
|
" 'text': 'we were going to a friends house when we got trapped into the riot against covid restrictions and a car got on fire and it was super bad to see all the anger all these people had i felt small and sad and i just wanted to run as faster as i could',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:43:45 GMT',\n",
|
||||||
|
" 'userID': '4164927552'},\n",
|
||||||
|
" {'image': 'rejection_map.jpg',\n",
|
||||||
|
" 'position': {'x': 33.8622, 'y': 34.9877},\n",
|
||||||
|
" 'size': {'height': 12.8237, 'width': 13.7806},\n",
|
||||||
|
" 'text': 'house rejection\\n',\n",
|
||||||
|
" 'timestamp': 'Wed, 15 Dec 2021 11:49:37 GMT',\n",
|
||||||
|
" 'userID': '4164927552'}]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"target_map('rejection_map.jpg', ['house', 'sad'])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "0c91b182-7541-4a79-a0f2-b2e688dd4371",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
title: "...and I wish that your question has been answered"
|
||||||
|
description: "An iterative process of refusal towards PM Kryakos Mitsotakis and PM Mark Rutte's answers"
|
||||||
|
url: "https://hub.xpub.nl/soupboat/~grgr/api/and_i_wish_that_your_question_has_been_answered/"
|
||||||
|
colophon: "Carmen, Grgr, Miriam, Mitsa"
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This is an act of persistent resistance. We created a few functions to facilitate an iterative process of refusal towards PM Kryakos Mitsotakis and PM Mark Rutte's answers during a Press Conference and any of their possible versions. We invite you to play as much as you want with these functions and create your own answers as counter-reaction to Mark Rutte's final sentence: "So this is my answer and I wish that your question has been answered".
|
||||||
|
Every new answer, every new iteration, can be submitted to our Archive of Repetitive Answers. Although they will never be good enough, nor shall they be accepted as exhaustive, we consider the modified answers as a trigger for a never-ending dialogue.
|
||||||
|
|
||||||
|
Our tool is a filter to process and alter texts. By targeting specific words and replacing them, either for another word, for specific characters or for blank spaces, the reader or user of the tool can change the text in many ways. The tool includes three functions
|
||||||
|
The function “respell” receives as input a text (string type) and substitute all the occurrences of a target word with a replacement chosen by the user.
|
||||||
|
The function “stitch” is very similar to the previous one but replaces all the occurrences of a target word with a single character (it can also be a blank space) that is repeated as many times as the length of the target.
|
||||||
|
The third function “reveal” also works very similar but deletes all input text except the target word(s) and replaces the deleted text with blank spaces.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
![text processing](https://hub.xpub.nl/soupboat/si16-app/static/img/mitsotakis_test.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### colophon
|
||||||
|
“...and I wish that your question has been answered.”
|
||||||
|
|
||||||
|
Mitsa (Dimitra Chaida), Erica Gargaglione, Carmen Gray, Miriam Schöb
|
||||||
|
|
||||||
|
December 2021
|
@ -0,0 +1,37 @@
|
|||||||
|
body {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.page--header {
|
||||||
|
width: auto;
|
||||||
|
top: 45px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.sections {
|
||||||
|
margin-top: 30vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
color: var(--textcolor);
|
||||||
|
row-gap:4vh;
|
||||||
|
}
|
||||||
|
.section {
|
||||||
|
position:relative
|
||||||
|
}
|
||||||
|
.reporter {
|
||||||
|
align-self: flex-start;
|
||||||
|
width: 70vw;
|
||||||
|
}
|
||||||
|
.answer {
|
||||||
|
align-self: flex-end;
|
||||||
|
width: 70vw;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
.reporter{
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.answer{
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
// Get the button, and when the user clicks on it, execute myFunction
|
||||||
|
//document.getElementById("info-btn").onclick = function() {showInfo()};
|
||||||
|
|
||||||
|
/* myFunction toggles between adding and removing the show class, which is used to hide and show the dropdown content */
|
||||||
|
function showInfo() {
|
||||||
|
document.getElementById("info").classList.toggle("show");
|
||||||
|
}
|
@ -0,0 +1,270 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: Pirelli;
|
||||||
|
src: url("./font/pirelli-regular.woff");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Pirelli;
|
||||||
|
src: url("./font/pirelli-bolditalic.woff");
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Necto-Mono;
|
||||||
|
src: url("./font/Necto-Mono.woff");
|
||||||
|
}
|
||||||
|
:root {
|
||||||
|
--red: tomato;
|
||||||
|
--background: rgb(233, 233, 233);
|
||||||
|
--textcolor: rgb(39, 39, 39);
|
||||||
|
--blue: #9edae2;
|
||||||
|
--pink: #f7d8e8;
|
||||||
|
--orange: #ffc496;
|
||||||
|
--yellow: #f9f5b0;
|
||||||
|
--green: #9fd3a8;
|
||||||
|
|
||||||
|
--content-width: 1440px;
|
||||||
|
--radius: 12px;
|
||||||
|
--font: "Pirelli";
|
||||||
|
--title: 36px;
|
||||||
|
--text: 24px;
|
||||||
|
--app-margin: 30px;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: Pirelli;
|
||||||
|
background-color: var(--background);
|
||||||
|
color: var(--textcolor);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
a.goto-archive {
|
||||||
|
position: fixed;
|
||||||
|
top: 16px;
|
||||||
|
right: 16px;
|
||||||
|
color: var(--red);
|
||||||
|
font-size: 1.2em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.page--header {
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
margin: 8vh 0;
|
||||||
|
padding: 0 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
column-gap: 8px;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-content: center;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.page--header > * {
|
||||||
|
border: solid 1px var(--red);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: var(--background);
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 36px;
|
||||||
|
color: var(--red);
|
||||||
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question {
|
||||||
|
display: flex;
|
||||||
|
font-size: 1.2em;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
row-gap: 24px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 28vh;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
/*background-color: white;*/
|
||||||
|
display: none;
|
||||||
|
padding: 16px;
|
||||||
|
border: solid 1px var(--red);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--red);
|
||||||
|
font-size: 1em;
|
||||||
|
flex-basis: 35%;
|
||||||
|
}
|
||||||
|
.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.q-text {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
flex-basis: 65%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*styling of form*/
|
||||||
|
form {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: wrap;
|
||||||
|
column-gap: 24px;
|
||||||
|
row-gap: 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.form-box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 8px;
|
||||||
|
flex-basis: 30%;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.form-box#apply {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
resize: none;
|
||||||
|
/* font-family: Necto-mono; */
|
||||||
|
border-radius: 4px;
|
||||||
|
border: solid 1px grey;
|
||||||
|
transition: border-radius 70ms ease-in-out;
|
||||||
|
}
|
||||||
|
/* when the cursor is iside the text area*/
|
||||||
|
textarea:focus {
|
||||||
|
border: solid 2px var(--red);
|
||||||
|
outline: none;
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-family: Pirelli;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
input:hover {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
/*to pick the exact type of input you wanna style use "[]"*/
|
||||||
|
input[type="radio"] {
|
||||||
|
font-family: Pirelli;
|
||||||
|
background-color: var(--red);
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*custom radio button*/
|
||||||
|
/* The container */
|
||||||
|
.radio-label {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 35px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.2em;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
/* Hide the browser's default radio button */
|
||||||
|
.radio-label input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a custom radio button */
|
||||||
|
.checkmark {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
border: solid 2px var(--red);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On mouse-over change color */
|
||||||
|
.radio-label:hover {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the radio button is checked, add a blue background */
|
||||||
|
.radio-label input:checked ~ .checkmark {
|
||||||
|
background-color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the indicator (the dot/circle - hidden when not checked) */
|
||||||
|
.checkmark:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lbl-result {
|
||||||
|
color: grey;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
.result {
|
||||||
|
font-family: Courier;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-end {
|
||||||
|
margin: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-flow: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
align-content: stretch;
|
||||||
|
column-gap: 8px;
|
||||||
|
}
|
||||||
|
.form-end > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-basis: 50%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
a.goto-form {
|
||||||
|
border: solid 1px rgb(107, 107, 107);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: Pirelli;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1.2em;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--textcolor);
|
||||||
|
text-align: center;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
.goto-form:hover {
|
||||||
|
color: var(--red);
|
||||||
|
background-color: rgb(216, 216, 216);
|
||||||
|
}
|
||||||
|
.save-btn {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
:root {
|
||||||
|
--app-margin: 18px;
|
||||||
|
--text: 21px;
|
||||||
|
}
|
||||||
|
.title,
|
||||||
|
nav.h1 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||||
|
<title>Archive</title>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="/soupboat/si16-app{{url_for('static', filename='font/font.css')}}"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="/soupboat/si16-app{{url_for('static', filename='css/variables.css')}}"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="/soupboat/si16-app{{url_for('static', filename='css/mitsotakis/style.css')}}" />
|
||||||
|
<link rel="stylesheet" href="/soupboat/si16-app{{url_for('static', filename='css/mitsotakis/archive.css')}}" />
|
||||||
|
<!-- <link rel="stylesheet" href="/soupboat/~grgr/flask{{url_for('static', filename='style.css')}}" /> -->
|
||||||
|
<link rel="stylesheet" href="/soupboat/si16-app/projects/and-i-wish-that-your-question-has-been-answered{{url_for('static', filename='archive.css')}}" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a class="goto-archive" href="https://hub.xpub.nl/soupboat/~grgr/api/and_i_wish_that_your_question_has_been_answered/">go to the form ⇝</a>
|
||||||
|
<section class="page--header">
|
||||||
|
<header>
|
||||||
|
<h1>Archive of Repetitive Answers</h1>
|
||||||
|
<h3>...and I wish that your question has been answered</h3>
|
||||||
|
</header>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!--<button onclick="window.print();" class="noPrint">Print!</button>-->
|
||||||
|
<div class='sections'>
|
||||||
|
<!-- {% for section in sections %}
|
||||||
|
{{section | safe}}
|
||||||
|
{% endfor %} -->
|
||||||
|
|
||||||
|
<!-- {%for answer in answers%}
|
||||||
|
<div class="answer">{{question | safe}}</div>
|
||||||
|
<div class="answer">{{answer | safe}}</div>
|
||||||
|
{%endfor%} -->
|
||||||
|
{%for answer in answers%}
|
||||||
|
<div class="answer">{{answer | safe}}</div>
|
||||||
|
<div class="reporter">{{question | safe}}</div>
|
||||||
|
|
||||||
|
|
||||||
|
{%endfor%}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,133 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||||
|
<title>Mitsotakis/?NO</title>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="/soupboat/si16-app{{url_for('static', filename='font/font.css')}}"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="/soupboat/si16-app{{url_for('static', filename='css/variables.css')}}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/soupboat/si16-app{{url_for('static', filename='css/mitsotakis/style.css')}}" />
|
||||||
|
<script src="/soupboat/si16-app{{url_for('static', filename='css/mitsotakis/script.js')}}')}}"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a class="goto-archive" href="https://hub.xpub.nl/soupboat/~grgr/api/archive/">go to archive ⇝</a>
|
||||||
|
<!-- <header>
|
||||||
|
<h1 id="title">...and I wish that your question has been answered.</h1>
|
||||||
|
<h1 id="info-btn" onclick="showInfo()">?</h1>
|
||||||
|
</header> -->
|
||||||
|
|
||||||
|
<section class="page--header">
|
||||||
|
<header>
|
||||||
|
<h1 class="title" id="title">
|
||||||
|
...and I wish that your question has been answered.
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
<nav role="button" id="info-btn" onclick="showInfo()">
|
||||||
|
<h1>?</h1>
|
||||||
|
</nav>
|
||||||
|
</section>
|
||||||
|
<div class="question">
|
||||||
|
<div class="info" id="info">
|
||||||
|
<p>This text is a transcribed excerpt from the Press Conference that followed the meeting between the Greek Prime Minister Kyriakos Mitsotakis and the Dutch Prime Minister Mark Rutte on November the 9th, 2021 in Athens. During the Q&A, the Dutch reporter Ingeborg Beugel asked Mitsotakis for clarity and honesty referring to pushbacks which Greek border guards keep committing towards refugees, while the Greek Government systematically conceals such violence. She continued by asking Mark Rutte what the political stance of the Netherlands towards refugees' relocation and Mitsotakis's policy would be.</p>
|
||||||
|
<p>The choice of this text as our source material has different reasons. First of all, we were interested in how language can produce categories and shape identities: how does wording create precise borders between the "us" and the "them"?
|
||||||
|
Our second step would be reflecting on text processing strategies through which a speech or a narration can be recontextualised and reclaimed. By replacing or taking out words of a discourse, and thus making some parts of it interchangeable, we tried to highlight how its phrasing is never neutral, but always a choice led by a particular purpose. </p>
|
||||||
|
<p>We decided to work on this text as the Press Conference took place at the moment we were developing our research, and as we were really interested on the distinctive rhetoric strategies that Beugel, Mitsotakis and Rutte choose for voicing their goals. It is clear that the reporter uses an emotional and provocative tone to address Mitsotakis' politics, which challenges his composure to a point where he can not keep it anymore, while when talking to Rutte, her speech is more calm and detached.
|
||||||
|
In response to her question, both Prime Ministers refuse responsibility of their actions: they use a rather managerial and pre-designed language to neutralize the reporter's provocation while at the same time praising the generosity and the efforts of their countries. In particular, Mitsotakis denies any of Beugel's accusations and declares them as unsupported assumptions which is a mere demonstration of power. Alongside, Rutte uses a colder and more restrained language to rationalize the EU and the Greek Government's choices: While shifting the responsibilities for refugee protection, he actually justifies the crimes that are committed within the EU borders as an inevitable "tough, but fair, policy".</p>
|
||||||
|
<p>Concerning our project, it is an act of persistent resistance. We created a few functions to facilitate an iterative process of refusal towards the two Prime Ministers' answers and any of their possible versions. We invite you to play as much as you want with these functions and create your own answers as counter-reaction to Mark Rutte's final sentence: "So this is my answer and I wish that your question has been answered".
|
||||||
|
Every new answer, every new iteration, can be submitted to our Archive of Repetitive Answers. Although they will never be good enough, nor shall they be accepted as exhaustive, we consider the modified answers as a trigger for a never-ending dialogue.</p>
|
||||||
|
</div>
|
||||||
|
<div class="q-text" id="test">{{question | safe}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="interaction" id="change-top">
|
||||||
|
<form
|
||||||
|
class="form-get"
|
||||||
|
action="/soupboat/~grgr/api/and_i_wish_that_your_question_has_been_answered/"
|
||||||
|
method="POST"
|
||||||
|
>
|
||||||
|
<div class="form-box">
|
||||||
|
<input name="text" type="hidden" value="{{result}}" />
|
||||||
|
<label for="target"
|
||||||
|
>type a word you would like to change in the following answer, if
|
||||||
|
you choose the function "reveal" you can type multiple words, but
|
||||||
|
separated by commas and with no spaces.
|
||||||
|
</label>
|
||||||
|
<textarea name="target" placeholder="target" autofocus></textarea>
|
||||||
|
<label for="f_replacement"
|
||||||
|
>type a replacement character or series of words, if you choose the
|
||||||
|
function "reveal" you don't have to type anything here.</label
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
name="f_replacement"
|
||||||
|
value=""
|
||||||
|
placeholder="replacement"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-box">
|
||||||
|
<label for="function">chose the function you want to apply</label>
|
||||||
|
<label class="radio-label" for="replace"
|
||||||
|
><input name="function" type="radio" value="replace" id="replace"{%
|
||||||
|
if function == 'replace'%} checked{%endif%}>respell<span
|
||||||
|
class="checkmark"
|
||||||
|
></span
|
||||||
|
></label>
|
||||||
|
<label class="radio-label" for="mend"
|
||||||
|
><input name="function" type="radio" value="mend" id="mend"{% if
|
||||||
|
function == 'mend'%} checked{%endif%}>stitch<span
|
||||||
|
class="checkmark"
|
||||||
|
></span
|
||||||
|
></label>
|
||||||
|
<label class="radio-label" for="underline"
|
||||||
|
><input name="function" type="radio" value="underline"
|
||||||
|
id="underline"{% if function == 'underline'%}
|
||||||
|
checked{%endif%}>reveal<span class="checkmark"></span
|
||||||
|
></label>
|
||||||
|
</div>
|
||||||
|
<!-- <label for="replace"><input name="function" type="radio" value="replace" id="replace"{% if function == 'replace'%} checked{%endif%}>respell</label>
|
||||||
|
<label for="mend"><input name="function" type="radio" value="mend" id="mend"{% if function == 'mend'%} checked{%endif%}>stitch</label>
|
||||||
|
<label for="underline"><input name="function" type="radio" value="underline" id="underline"{% if function == 'underline'%} checked{%endif%}>reveal</label> -->
|
||||||
|
<div class="form-box" id="apply">
|
||||||
|
<input type="submit" value="apply" name="keep" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="result"
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
column-gap: 24px;
|
||||||
|
width: 70vw;
|
||||||
|
margin: 0 auto;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div style="width: 50%">
|
||||||
|
<p class="lbl-result"><em>original text</em></p>
|
||||||
|
<p style="white-space: break-spaces">{{source | safe}}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="width: 50%">
|
||||||
|
<p class="lbl-result"><em>modified version</em></p>
|
||||||
|
<p style="white-space: break-spaces">{{result | safe}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-end">
|
||||||
|
<a class="goto-form" href="#change-top">continue to change the answers</a>
|
||||||
|
<form action="/soupboat/~grgr/api/save/" method="POST">
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
value="save to archive"
|
||||||
|
name="post"
|
||||||
|
class="save-btn"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,229 @@
|
|||||||
|
#
|
||||||
|
#
|
||||||
|
# DEPENDENCIES
|
||||||
|
import os
|
||||||
|
from flask import Flask, url_for, render_template, flash, request, redirect
|
||||||
|
from werkzeug.utils import secure_filename
|
||||||
|
import json
|
||||||
|
import mariadb
|
||||||
|
import sys
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# GLOBAL VARIABLES
|
||||||
|
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'static/uploads/annotation-compass/')
|
||||||
|
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FUNCTIONS
|
||||||
|
|
||||||
|
def connection():
|
||||||
|
''' Open a connection to the mariaDB database '''
|
||||||
|
try:
|
||||||
|
conn = mariadb.connect(
|
||||||
|
user="guardian_of_the_labels",
|
||||||
|
password="soup_of_the_labels",
|
||||||
|
host="localhost",
|
||||||
|
port=3306,
|
||||||
|
database='collecting_labels',
|
||||||
|
autocommit=True
|
||||||
|
)
|
||||||
|
except mariadb.Error as e:
|
||||||
|
print(f'Error connecting to MariaDB Platflorm: {e}')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
def make_link_list(names, base_url):
|
||||||
|
''' Generate a list of link from the files in a folder '''
|
||||||
|
link_list = ''
|
||||||
|
for name in names:
|
||||||
|
if allowed_file(name, ALLOWED_EXTENSIONS):
|
||||||
|
link = f'<a href="{base_url}/{name}/">{name}</a><br/>'
|
||||||
|
link_list = link_list + link
|
||||||
|
return link_list
|
||||||
|
|
||||||
|
|
||||||
|
def allowed_file(filename, extensions):
|
||||||
|
''' Check if the file extension is in the allowed extensions array '''
|
||||||
|
return '.' in filename and \
|
||||||
|
filename.rsplit('.', 1)[1].lower() in extensions
|
||||||
|
|
||||||
|
|
||||||
|
def temp_fix_date(timestamp):
|
||||||
|
''' JS Date to mySQL Date '''
|
||||||
|
from datetime import datetime
|
||||||
|
from time import strftime
|
||||||
|
date = datetime.fromtimestamp(timestamp / 1000.0)
|
||||||
|
return date.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
|
||||||
|
def add_label(cursor, label):
|
||||||
|
''' Insert a new label in the database '''
|
||||||
|
x = label['position']['x']
|
||||||
|
y = label['position']['y']
|
||||||
|
width = label['size']['width']
|
||||||
|
height = label['size']['height']
|
||||||
|
text = label['text']
|
||||||
|
timestamp = temp_fix_date(label['timestamp'])
|
||||||
|
user_id = str(label['userID'])
|
||||||
|
image = label['image']
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute(f'INSERT INTO labels (x,y,width,height,text,timestamp,userID,image) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', (x, y, width, height, text, timestamp, user_id, image ))
|
||||||
|
print(f'Insert label#{cursor.lastrowid} from user {user_id} on {image} at {timestamp}.')
|
||||||
|
except mariadb.Error as e:
|
||||||
|
print(f"Error error error in MariaDB Platform: {e}")
|
||||||
|
return {"message":"oh no", "error":e}
|
||||||
|
|
||||||
|
|
||||||
|
def get_labels(cursor, filename):
|
||||||
|
''' List the labels for a specific image from the database '''
|
||||||
|
try:
|
||||||
|
cursor.execute(f"SELECT * FROM labels WHERE image = '{filename}'")
|
||||||
|
db_labels = cursor.fetchall()
|
||||||
|
labels = []
|
||||||
|
for (index, x, y, width, height, text, timestamp, user_id, image) in db_labels:
|
||||||
|
label = {
|
||||||
|
'position': {
|
||||||
|
'x': x,
|
||||||
|
'y': y
|
||||||
|
},
|
||||||
|
'size': {
|
||||||
|
'width': width,
|
||||||
|
'height': height
|
||||||
|
},
|
||||||
|
'text': text,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'userID': user_id,
|
||||||
|
'image': image
|
||||||
|
}
|
||||||
|
labels.append(label)
|
||||||
|
return labels
|
||||||
|
except mariadb.Error as e:
|
||||||
|
print(f"Error error error in MariaDB Platform: {e}")
|
||||||
|
return {"message":"oh no", "error":e}
|
||||||
|
|
||||||
|
|
||||||
|
def add_image_description(filename, description):
|
||||||
|
''' Set description for an image during upload '''
|
||||||
|
image_description_output = {}
|
||||||
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
|
||||||
|
image_description_input = json.loads(f.read())
|
||||||
|
image_description_output = image_description_input
|
||||||
|
image_description_output[filename] = {
|
||||||
|
'description': description
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "w") as f:
|
||||||
|
f.write(json.dumps(image_description_output))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_image_description(filename):
|
||||||
|
''' Get the description of an uploaded image '''
|
||||||
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
|
||||||
|
descriptions = json.loads(f.read())
|
||||||
|
return descriptions[filename]['description']
|
||||||
|
|
||||||
|
|
||||||
|
def thumbnail(image):
|
||||||
|
try:
|
||||||
|
img = Image.open(image)
|
||||||
|
img.thumbnail((128,128))
|
||||||
|
name = image.rsplit('.', 1)[0]
|
||||||
|
ext = image.rsplit('.', 1)[1]
|
||||||
|
img.save(f'{name}_thumb.{ext}')
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: clean up this dai
|
||||||
|
# /generic-labels/ → /si16/annotation-compass/ (GET, POST)
|
||||||
|
def upload_file(request):
|
||||||
|
''' Upload a new image in the Annotation Compass '''
|
||||||
|
# check if the post request has the file part
|
||||||
|
if 'file' not in request.files:
|
||||||
|
flash('No file part')
|
||||||
|
return redirect(request.url)
|
||||||
|
file = request.files['file']
|
||||||
|
# If the user does not select a file, the browser submits an
|
||||||
|
# empty file without a filename.
|
||||||
|
if file.filename == '':
|
||||||
|
flash('No selected file')
|
||||||
|
return redirect(request.url)
|
||||||
|
if file and allowed_file(file.filename, ALLOWED_EXTENSIONS):
|
||||||
|
filename = secure_filename(file.filename)
|
||||||
|
file.save(os.path.join(UPLOAD_FOLDER, filename))
|
||||||
|
thumbnail(os.path.join(UPLOAD_FOLDER, filename))
|
||||||
|
description = request.form['description']
|
||||||
|
add_image_description(filename, description)
|
||||||
|
|
||||||
|
|
||||||
|
def list_images():
|
||||||
|
''' List the images in the Annotation Compass. '''
|
||||||
|
files = os.listdir(UPLOAD_FOLDER)
|
||||||
|
files.sort()
|
||||||
|
|
||||||
|
not_thumbs = filter(lambda file: '_thumb.' not in file, files)
|
||||||
|
|
||||||
|
images = []
|
||||||
|
for image in not_thumbs:
|
||||||
|
if allowed_file(image, ALLOWED_EXTENSIONS):
|
||||||
|
name = image.rsplit('.', 1)[0]
|
||||||
|
ext = image.rsplit('.', 1)[1]
|
||||||
|
img = image
|
||||||
|
thumb = f'{name}_thumb.{ext}'
|
||||||
|
images.append((img, thumb))
|
||||||
|
return images
|
||||||
|
|
||||||
|
# links = make_link_list(images, 'annotate/' )
|
||||||
|
|
||||||
|
# TODO: transform this in a template
|
||||||
|
# return f'''
|
||||||
|
# <!doctype html>
|
||||||
|
# <title>Collecting Labels</title>
|
||||||
|
# {links}
|
||||||
|
# <h2>Upload new File</h2>
|
||||||
|
# <form method=post enctype=multipart/form-data>
|
||||||
|
# <input type=file name=file>
|
||||||
|
# <input type=submit value=Upload>
|
||||||
|
# <textarea name=description ></textarea>
|
||||||
|
# </form>
|
||||||
|
# '''
|
||||||
|
|
||||||
|
# /generic-labels/annotate/<image>/ → /si16/annotation-compass/annotate/<image>/
|
||||||
|
# def annotate_image(image=None):
|
||||||
|
# ''' Open the Annotation Compass on a specific image '''
|
||||||
|
# description = ''
|
||||||
|
# try:
|
||||||
|
# description = get_image_description(image)
|
||||||
|
# except:
|
||||||
|
# print("There is no description")
|
||||||
|
# return render_template('annotate_image.html', image=image, description=description)
|
||||||
|
|
||||||
|
|
||||||
|
# /generic-labels/add-label/ → /si16/annotation-compass/add-label
|
||||||
|
# in the URL there is no reference to the image because the info is in the json body of the label itself
|
||||||
|
def insert_label(request):
|
||||||
|
''' Insert a new label in the database '''
|
||||||
|
connect = connection()
|
||||||
|
cursor = connect.cursor()
|
||||||
|
add_label(cursor, request.json)
|
||||||
|
connect.close()
|
||||||
|
return {"response": "ok"}
|
||||||
|
|
||||||
|
# /generic-labels/get-labels/ → /si16/annotation-compass/get-labels/<image>/
|
||||||
|
# TODO: adapt the old url with the query
|
||||||
|
# OLD: /get-labels/?image=<image>
|
||||||
|
# NEW: /get-labels/<image>/
|
||||||
|
|
||||||
|
def get_labels_list(image = None):
|
||||||
|
connect = connection()
|
||||||
|
cursor = connect.cursor()
|
||||||
|
labels = get_labels(cursor, image)
|
||||||
|
connect.close()
|
||||||
|
return {"response": "ok", "labels": labels }
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -0,0 +1,229 @@
|
|||||||
|
#
|
||||||
|
#
|
||||||
|
# DEPENDENCIES
|
||||||
|
import os
|
||||||
|
from flask import Flask, url_for, render_template, flash, request, redirect
|
||||||
|
from werkzeug.utils import secure_filename
|
||||||
|
import json
|
||||||
|
import mariadb
|
||||||
|
import sys
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# GLOBAL VARIABLES
|
||||||
|
UPLOAD_FOLDER = os.path.join(os.getcwd(), 'static/uploads/annotation-compass/')
|
||||||
|
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FUNCTIONS
|
||||||
|
|
||||||
|
def connection():
|
||||||
|
''' Open a connection to the mariaDB database '''
|
||||||
|
try:
|
||||||
|
conn = mariadb.connect(
|
||||||
|
user="guardian_of_the_labels",
|
||||||
|
password="soup_of_the_labels",
|
||||||
|
host="localhost",
|
||||||
|
port=3306,
|
||||||
|
database='collecting_labels',
|
||||||
|
autocommit=True
|
||||||
|
)
|
||||||
|
except mariadb.Error as e:
|
||||||
|
print(f'Error connecting to MariaDB Platflorm: {e}')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
def make_link_list(names, base_url):
|
||||||
|
''' Generate a list of link from the files in a folder '''
|
||||||
|
link_list = ''
|
||||||
|
for name in names:
|
||||||
|
if allowed_file(name, ALLOWED_EXTENSIONS):
|
||||||
|
link = f'<a href="{base_url}/{name}/">{name}</a><br/>'
|
||||||
|
link_list = link_list + link
|
||||||
|
return link_list
|
||||||
|
|
||||||
|
|
||||||
|
def allowed_file(filename, extensions):
|
||||||
|
''' Check if the file extension is in the allowed extensions array '''
|
||||||
|
return '.' in filename and \
|
||||||
|
filename.rsplit('.', 1)[1].lower() in extensions
|
||||||
|
|
||||||
|
|
||||||
|
def temp_fix_date(timestamp):
|
||||||
|
''' JS Date to mySQL Date '''
|
||||||
|
from datetime import datetime
|
||||||
|
from time import strftime
|
||||||
|
date = datetime.fromtimestamp(timestamp / 1000.0)
|
||||||
|
return date.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
|
||||||
|
def add_label(cursor, label):
|
||||||
|
''' Insert a new label in the database '''
|
||||||
|
x = label['position']['x']
|
||||||
|
y = label['position']['y']
|
||||||
|
width = label['size']['width']
|
||||||
|
height = label['size']['height']
|
||||||
|
text = label['text']
|
||||||
|
timestamp = temp_fix_date(label['timestamp'])
|
||||||
|
user_id = str(label['userID'])
|
||||||
|
image = label['image']
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute(f'INSERT INTO labels (x,y,width,height,text,timestamp,userID,image) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', (x, y, width, height, text, timestamp, user_id, image ))
|
||||||
|
print(f'Insert label#{cursor.lastrowid} from user {user_id} on {image} at {timestamp}.')
|
||||||
|
except mariadb.Error as e:
|
||||||
|
print(f"Error error error in MariaDB Platform: {e}")
|
||||||
|
return {"message":"oh no", "error":e}
|
||||||
|
|
||||||
|
|
||||||
|
def get_labels(cursor, filename):
|
||||||
|
''' List the labels for a specific image from the database '''
|
||||||
|
try:
|
||||||
|
cursor.execute(f"SELECT * FROM labels WHERE image = '{filename}'")
|
||||||
|
db_labels = cursor.fetchall()
|
||||||
|
labels = []
|
||||||
|
for (index, x, y, width, height, text, timestamp, user_id, image) in db_labels:
|
||||||
|
label = {
|
||||||
|
'position': {
|
||||||
|
'x': x,
|
||||||
|
'y': y
|
||||||
|
},
|
||||||
|
'size': {
|
||||||
|
'width': width,
|
||||||
|
'height': height
|
||||||
|
},
|
||||||
|
'text': text,
|
||||||
|
'timestamp': timestamp,
|
||||||
|
'userID': user_id,
|
||||||
|
'image': image
|
||||||
|
}
|
||||||
|
labels.append(label)
|
||||||
|
return labels
|
||||||
|
except mariadb.Error as e:
|
||||||
|
print(f"Error error error in MariaDB Platform: {e}")
|
||||||
|
return {"message":"oh no", "error":e}
|
||||||
|
|
||||||
|
|
||||||
|
def add_image_description(filename, description):
|
||||||
|
''' Set description for an image during upload '''
|
||||||
|
image_description_output = {}
|
||||||
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
|
||||||
|
image_description_input = json.loads(f.read())
|
||||||
|
image_description_output = image_description_input
|
||||||
|
image_description_output[filename] = {
|
||||||
|
'description': description
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "w") as f:
|
||||||
|
f.write(json.dumps(image_description_output))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_image_description(filename):
|
||||||
|
''' Get the description of an uploaded image '''
|
||||||
|
with open(os.path.join(os.getcwd(), "projects/annotation-compass/descriptions.json"), "r") as f:
|
||||||
|
descriptions = json.loads(f.read())
|
||||||
|
return descriptions[filename]['description']
|
||||||
|
|
||||||
|
|
||||||
|
def thumbnail(image):
|
||||||
|
try:
|
||||||
|
img = Image.open(image)
|
||||||
|
img.thumbnail((128,128))
|
||||||
|
name = image.rsplit('.', 1)[0]
|
||||||
|
ext = image.rsplit('.', 1)[1]
|
||||||
|
img.save(f'{name}_thumb.{ext}')
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: clean up this dai
|
||||||
|
# /generic-labels/ → /si16/annotation-compass/ (GET, POST)
|
||||||
|
def upload_file(request):
|
||||||
|
''' Upload a new image in the Annotation Compass '''
|
||||||
|
# check if the post request has the file part
|
||||||
|
if 'file' not in request.files:
|
||||||
|
flash('No file part')
|
||||||
|
return redirect(request.url)
|
||||||
|
file = request.files['file']
|
||||||
|
# If the user does not select a file, the browser submits an
|
||||||
|
# empty file without a filename.
|
||||||
|
if file.filename == '':
|
||||||
|
flash('No selected file')
|
||||||
|
return redirect(request.url)
|
||||||
|
if file and allowed_file(file.filename, ALLOWED_EXTENSIONS):
|
||||||
|
filename = secure_filename(file.filename)
|
||||||
|
file.save(os.path.join(UPLOAD_FOLDER, filename))
|
||||||
|
thumbnail(os.path.join(UPLOAD_FOLDER, filename))
|
||||||
|
description = request.form['description']
|
||||||
|
add_image_description(filename, description)
|
||||||
|
|
||||||
|
|
||||||
|
def list_images():
|
||||||
|
''' List the images in the Annotation Compass. '''
|
||||||
|
files = os.listdir(UPLOAD_FOLDER)
|
||||||
|
files.sort()
|
||||||
|
|
||||||
|
not_thumbs = filter(lambda file: '_thumb.' not in file, files)
|
||||||
|
|
||||||
|
images = []
|
||||||
|
for image in not_thumbs:
|
||||||
|
if allowed_file(image, ALLOWED_EXTENSIONS):
|
||||||
|
name = image.rsplit('.', 1)[0]
|
||||||
|
ext = image.rsplit('.', 1)[1]
|
||||||
|
img = image
|
||||||
|
thumb = f'{name}_thumb.{ext}'
|
||||||
|
images.append((img, thumb))
|
||||||
|
return images
|
||||||
|
|
||||||
|
# links = make_link_list(images, 'annotate/' )
|
||||||
|
|
||||||
|
# TODO: transform this in a template
|
||||||
|
# return f'''
|
||||||
|
# <!doctype html>
|
||||||
|
# <title>Collecting Labels</title>
|
||||||
|
# {links}
|
||||||
|
# <h2>Upload new File</h2>
|
||||||
|
# <form method=post enctype=multipart/form-data>
|
||||||
|
# <input type=file name=file>
|
||||||
|
# <input type=submit value=Upload>
|
||||||
|
# <textarea name=description ></textarea>
|
||||||
|
# </form>
|
||||||
|
# '''
|
||||||
|
|
||||||
|
# /generic-labels/annotate/<image>/ → /si16/annotation-compass/annotate/<image>/
|
||||||
|
# def annotate_image(image=None):
|
||||||
|
# ''' Open the Annotation Compass on a specific image '''
|
||||||
|
# description = ''
|
||||||
|
# try:
|
||||||
|
# description = get_image_description(image)
|
||||||
|
# except:
|
||||||
|
# print("There is no description")
|
||||||
|
# return render_template('annotate_image.html', image=image, description=description)
|
||||||
|
|
||||||
|
|
||||||
|
# /generic-labels/add-label/ → /si16/annotation-compass/add-label
|
||||||
|
# in the URL there is no reference to the image because the info is in the json body of the label itself
|
||||||
|
def insert_label(request):
|
||||||
|
''' Insert a new label in the database '''
|
||||||
|
connect = connection()
|
||||||
|
cursor = connect.cursor()
|
||||||
|
add_label(cursor, request.json)
|
||||||
|
connect.close()
|
||||||
|
return {"response": "ok"}
|
||||||
|
|
||||||
|
# /generic-labels/get-labels/ → /si16/annotation-compass/get-labels/<image>/
|
||||||
|
# TODO: adapt the old url with the query
|
||||||
|
# OLD: /get-labels/?image=<image>
|
||||||
|
# NEW: /get-labels/<image>/
|
||||||
|
|
||||||
|
def get_labels_list(image = None):
|
||||||
|
connect = connection()
|
||||||
|
cursor = connect.cursor()
|
||||||
|
labels = get_labels(cursor, image)
|
||||||
|
connect.close()
|
||||||
|
return {"response": "ok", "labels": labels }
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
title: Infiltrating the Filter
|
||||||
|
author: Supisara
|
||||||
|
colophon: A showcase of the 'Annotation Compass'
|
||||||
|
description: Alternative annotation approaches
|
||||||
|
template:
|
||||||
|
---
|
@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
title: Rotterdam Impressions
|
||||||
|
author: Ål Nik (Alexandra Nikolova)
|
||||||
|
colophon: A showcase of the 'Annotation Compass'
|
||||||
|
description: A collective map of Rotterdam impressions, annotated by the first year Experimental Publishing students
|
||||||
|
functions: Adjectives, Nouns filers, Most common words filter
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
### rotterdam impressions with the 'annotation compass'
|
||||||
|
We all arrived here from different places, backgrounds, histories and languages. As a group, we are building our relationships and exploring our personalities. Brought to this new place, we discover it both individually and collectively. The city is our everyday environment - we navigate in it to go to school, to go home, to do our grocery, to have a drink out. We spend some of these moments alone, sometimes with someone else. In a short moment of reflection, we all remembered our first or strongest impressions of some particular areas of Rotterdam, which triggered a memorable emotion in us.
|
||||||
|
|
||||||
|
These illustrated subjective maps represent the impressions of the first year master students of Experimental Publishing at the Piet Zwart Institute. Their situated experiences trigger various ways to describe their new home: Rotterdam. They were invited to reflect on the way they remember some of the areas in the city and to describe how they feel about them. In words, in their own vernacular English - the common language that is not native to anyone of them but the main language they communicate between each other. Afterwards, their descriptions were filtered by a Python function to extract the most common words they used whilst describing their perceptions of the selected areas on the map, divided in three main categories - adjectives, nouns and pronouns. The final outcome is this short list of the most common impressions of various places and illustrated maps as an artistic expression of the author.
|
||||||
|
|
||||||
|
### the most common...
|
||||||
|
In the following lists we observe the most common words the annotators used in their descriptions. They were asked to describe how they feel about areas and places they see on the map which trigger some memories and emotions in them. By using the Python filters for extracting the words that are adjectives (the words people used to describe their impressions of Rotterdam and various areas and places in it), nouns (the objects that we see people referring to) and pronouns (they way the approached the reflection) in combination with a filter for the most common words (which shows us which words are used the most and how many times), we can observe what are the feelings and impressions that they share as a new collective. What are the places and emotions that are common for some of them?
|
||||||
|
|
||||||
|
```python
|
||||||
|
[('I', 53), ('my', 21), ('we', 19), ('me', 16), ('i', 13), ('place', 9), ('super', 9), ('We', 9), ('happy', 8), ('excited', 8), ('our', 8), ('were', 8), ('beautiful', 7), ('Rotterdam', 7), ('first', 6), ('area', 6), ('calm', 5), ('nervous', 5), ('big', 5), ('fig', 5), ('tree', 5), ('safe', 4), ('home', 4), ('inspired', 4), ('city', 4), ('little', 4), ('room', 4), ('shocked', 4), ('fun', 3), ('frustrated', 3), ('friendly', 3), ('good', 3), ('best', 3), ('bridge', 3), ('school', 3), ('nice', 3), ('station', 3), ('weird', 3), ('sad', 3), ('bike', 3), ('neighborhood', 3)]
|
||||||
|
```
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_00.jpg)
|
||||||
|
|
||||||
|
### vernacular map
|
||||||
|
The visual maps of [rotterdam impressions] depict how many times specific words were mentioned in the descriptions overall - the positions of the words are not related to the specific areas where they were mentioned because they are a collective print of how many times these words were used anywhere on the map. By printing each time a word was used, we can see the intensity of words used by the annotators. They are coloured due to their category - adjectives are in green, nouns are in orange and pronouns - in pink.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_01.jpg)
|
||||||
|
|
||||||
|
### how are we describing
|
||||||
|
"I" and "we" are the most common pronouns (in pink) that were used in the annotations. You can see that "I" was used as twice more often that "we", but perhaps because of the context of us describing our first impressions of a new place where everyone arrived to study and work together as a group, some of the experiences were still connected to a collective moment.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_03.jpg)
|
||||||
|
|
||||||
|
### adjectives as emotions and impressions; nouns as objects
|
||||||
|
In the context of the annotation compass, the adjectives (in green) were filtered and extracted as impressions and descriptions of the new place where people arrived. They are either describing Rotterdam and places inside it, or the way the annotator feels about them. Either way, in most of the cases we can still get the emotion that lays behind the word used. The most common nouns are understood as the objects (in orange) - the ones people are relating most often to.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_04.jpg)
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_02.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
To filter the adjectives from the annotations:
|
||||||
|
|
||||||
|
```
|
||||||
|
def adjectives(text):
|
||||||
|
adj = []
|
||||||
|
for (word, tag) in labels_blob.tags:
|
||||||
|
if tag == 'JJ':
|
||||||
|
adj = adj + [word]
|
||||||
|
return adj
|
||||||
|
```
|
||||||
|
|
||||||
|
To filter the nouns from the annotations:
|
||||||
|
|
||||||
|
```
|
||||||
|
def nouns(text):
|
||||||
|
noun = []
|
||||||
|
for (word, tag) in labels_blob.tags:
|
||||||
|
if tag == 'NN':
|
||||||
|
noun = noun + [word]
|
||||||
|
return noun
|
||||||
|
```
|
||||||
|
|
||||||
|
To filter the most common words from the annotations:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
def most_common(words):
|
||||||
|
freq_dist_pos = FreqDist(words)
|
||||||
|
return freq_dist_pos.most_common(100)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
Getting to the final showcase of the "annotation compass" was a long way of going back and forth whilst learning my first steps in Python. From the beginning my idea was to create vernacular map of our rotterdam impressions using our words in describing emotions and experineces. Here is what happened on the road:
|
||||||
|
|
||||||
|
### 0. background story
|
||||||
|
In May 2021 I went through a massive burnout which resulted in me going to the hospital and not being able to climb the stairs at home normally for a week, because I couldn't take a deep breath. This traumatic experience got me started paying more attention to the signs of me getting overwhelmed; and also since then I have been living in fear of going through a similar experience again.
|
||||||
|
|
||||||
|
After that crazy time, I had to organise my moving to Rotterdam and do some work on the way around Europe. After a year in isolation because of the pandemic, this was a dramatic change and I was afraid I might have another panic attack whilst being alone in the train in the middle of nowhere. In order to keep a track of my emotions and the way I feel, I started mapping them. That experiment made me think more of how to use our "annotation compass" to map our group's experiences and feelings.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/prototype_00.jpg)
|
||||||
|
|
||||||
|
### 1. ideas & prototypes
|
||||||
|
The initial idea was to try mapping our emotions when reflecting on our first experiences in Rotterdam. In order to visualise that, I made a few prototypes by me mapping the places I feel most strongly about and then doing the same with my colleague Supisara.
|
||||||
|
|
||||||
|
The prototypes were adjectives put on the map of Rotterdam, describing how we felt about a specific place or area. Later on, I figured it would be much more interesting to give freedom to the annotator to choose how they want to describe their perceptions. And after that, I could filter their texts in order to extract the adjectives.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/prototype_01.jpg)
|
||||||
|
|
||||||
|
### 2. collecting annotations
|
||||||
|
|
||||||
|
We used the "annotation compass" to write down some reflections about our arrival in Rotterdam and the way we feel about some places and areas. The invitation to the group was to take a few minutes to reflect on their arrival in the city and they feel strongly on some areas and spaces; and to describe the way they feel about them.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/prototype_02.jpg)
|
||||||
|
|
||||||
|
### 3. filtering the annotations with python
|
||||||
|
Since there was no restriction what words the use in the descriptions, I applied a combination of Python functions in order to process the data and extract the most common words. I also looked up for how many times the most common adjectives, nouns and pronouns were used. Looking at the result of the text processing, I created illustrated maps with the number of times these most common words were used.
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: Infiltrating the Filter
|
||||||
|
author: Supisara
|
||||||
|
colophon: A showcase of the 'Annotation Compass'
|
||||||
|
description: Alternative approaches to annotating
|
||||||
|
template:
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
title: Rotterdam Impressions
|
||||||
|
author: Ål Nik (Alexandra Nikolova)
|
||||||
|
colophon: A showcase of the 'Annotation Compass'
|
||||||
|
description: A collective map of Rotterdam impressions, annotated by the first year Experimental Publishing students
|
||||||
|
functions: Adjectives, Nouns filers, Most common words filter
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
### rotterdam impressions with the 'annotation compass'
|
||||||
|
We all arrived here from different places, backgrounds, histories and languages. As a group, we are building our relationships and exploring our personalities. Brought to this new place, we discover it both individually and collectively. The city is our everyday environment - we navigate in it to go to school, to go home, to do our grocery, to have a drink out. We spend some of these moments alone, sometimes with someone else. In a short moment of reflection, we all remembered our first or strongest impressions of some particular areas of Rotterdam, which triggered a memorable emotion in us.
|
||||||
|
|
||||||
|
These illustrated subjective maps represent the impressions of the first year master students of Experimental Publishing at the Piet Zwart Institute. Their situated experiences trigger various ways to describe their new home: Rotterdam. They were invited to reflect on the way they remember some of the areas in the city and to describe how they feel about them. In words, in their own vernacular English - the common language that is not native to anyone of them but the main language they communicate between each other. Afterwards, their descriptions were filtered by a Python function to extract the most common words they used whilst describing their perceptions of the selected areas on the map, divided in three main categories - adjectives, nouns and pronouns. The final outcome is this short list of the most common impressions of various places and illustrated maps as an artistic expression of the author.
|
||||||
|
|
||||||
|
### the most common...
|
||||||
|
In the following lists we observe the most common words the annotators used in their descriptions. They were asked to describe how they feel about areas and places they see on the map which trigger some memories and emotions in them. By using the Python filters for extracting the words that are adjectives (the words people used to describe their impressions of Rotterdam and various areas and places in it), nouns (the objects that we see people referring to) and pronouns (they way the approached the reflection) in combination with a filter for the most common words (which shows us which words are used the most and how many times), we can observe what are the feelings and impressions that they share as a new collective. What are the places and emotions that are common for some of them?
|
||||||
|
|
||||||
|
```python
|
||||||
|
[('I', 53), ('my', 21), ('we', 19), ('me', 16), ('i', 13), ('place', 9), ('super', 9), ('We', 9), ('happy', 8), ('excited', 8), ('our', 8), ('were', 8), ('beautiful', 7), ('Rotterdam', 7), ('first', 6), ('area', 6), ('calm', 5), ('nervous', 5), ('big', 5), ('fig', 5), ('tree', 5), ('safe', 4), ('home', 4), ('inspired', 4), ('city', 4), ('little', 4), ('room', 4), ('shocked', 4), ('fun', 3), ('frustrated', 3), ('friendly', 3), ('good', 3), ('best', 3), ('bridge', 3), ('school', 3), ('nice', 3), ('station', 3), ('weird', 3), ('sad', 3), ('bike', 3), ('neighborhood', 3)]
|
||||||
|
```
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_00.jpg)
|
||||||
|
|
||||||
|
### vernacular map
|
||||||
|
The visual maps of [rotterdam impressions] depict how many times specific words were mentioned in the descriptions overall - the positions of the words are not related to the specific areas where they were mentioned because they are a collective print of how many times these words were used anywhere on the map. By printing each time a word was used, we can see the intensity of words used by the annotators. They are coloured due to their category - adjectives are in green, nouns are in orange and pronouns - in pink.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_01.jpg)
|
||||||
|
|
||||||
|
### how are we describing
|
||||||
|
"I" and "we" are the most common pronouns (in pink) that were used in the annotations. You can see that "I" was used as twice more often that "we", but perhaps because of the context of us describing our first impressions of a new place where everyone arrived to study and work together as a group, some of the experiences were still connected to a collective moment.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_03.jpg)
|
||||||
|
|
||||||
|
### adjectives as emotions and impressions; nouns as objects
|
||||||
|
In the context of the annotation compass, the adjectives (in green) were filtered and extracted as impressions and descriptions of the new place where people arrived. They are either describing Rotterdam and places inside it, or the way the annotator feels about them. Either way, in most of the cases we can still get the emotion that lays behind the word used. The most common nouns are understood as the objects (in orange) - the ones people are relating most often to.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_04.jpg)
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/map_02.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
To filter the adjectives from the annotations:
|
||||||
|
|
||||||
|
```
|
||||||
|
def adjectives(text):
|
||||||
|
adj = []
|
||||||
|
for (word, tag) in labels_blob.tags:
|
||||||
|
if tag == 'JJ':
|
||||||
|
adj = adj + [word]
|
||||||
|
return adj
|
||||||
|
```
|
||||||
|
|
||||||
|
To filter the nouns from the annotations:
|
||||||
|
|
||||||
|
```
|
||||||
|
def nouns(text):
|
||||||
|
noun = []
|
||||||
|
for (word, tag) in labels_blob.tags:
|
||||||
|
if tag == 'NN':
|
||||||
|
noun = noun + [word]
|
||||||
|
return noun
|
||||||
|
```
|
||||||
|
|
||||||
|
To filter the most common words from the annotations:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
def most_common(words):
|
||||||
|
freq_dist_pos = FreqDist(words)
|
||||||
|
return freq_dist_pos.most_common(100)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
Getting to the final showcase of the "annotation compass" was a long way of going back and forth whilst learning my first steps in Python. From the beginning my idea was to create vernacular map of our rotterdam impressions using our words in describing emotions and experineces. Here is what happened on the road:
|
||||||
|
|
||||||
|
### 0. background story
|
||||||
|
In May 2021 I went through a massive burnout which resulted in me going to the hospital and not being able to climb the stairs at home normally for a week, because I couldn't take a deep breath. This traumatic experience got me started paying more attention to the signs of me getting overwhelmed; and also since then I have been living in fear of going through a similar experience again.
|
||||||
|
|
||||||
|
After that crazy time, I had to organise my moving to Rotterdam and do some work on the way around Europe. After a year in isolation because of the pandemic, this was a dramatic change and I was afraid I might have another panic attack whilst being alone in the train in the middle of nowhere. In order to keep a track of my emotions and the way I feel, I started mapping them. That experiment made me think more of how to use our "annotation compass" to map our group's experiences and feelings.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/prototype_00.jpg)
|
||||||
|
|
||||||
|
### 1. ideas & prototypes
|
||||||
|
The initial idea was to try mapping our emotions when reflecting on our first experiences in Rotterdam. In order to visualise that, I made a few prototypes by me mapping the places I feel most strongly about and then doing the same with my colleague Supisara.
|
||||||
|
|
||||||
|
The prototypes were adjectives put on the map of Rotterdam, describing how we felt about a specific place or area. Later on, I figured it would be much more interesting to give freedom to the annotator to choose how they want to describe their perceptions. And after that, I could filter their texts in order to extract the adjectives.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/prototype_01.jpg)
|
||||||
|
|
||||||
|
### 2. collecting annotations
|
||||||
|
|
||||||
|
We used the "annotation compass" to write down some reflections about our arrival in Rotterdam and the way we feel about some places and areas. The invitation to the group was to take a few minutes to reflect on their arrival in the city and they feel strongly on some areas and spaces; and to describe the way they feel about them.
|
||||||
|
|
||||||
|
![Screenshot of the result](/soupboat/si16-app/static/img/rotterdam_impressions/prototype_02.jpg)
|
||||||
|
|
||||||
|
### 3. filtering the annotations with python
|
||||||
|
Since there was no restriction what words the use in the descriptions, I applied a combination of Python functions in order to process the data and extract the most common words. I also looked up for how many times the most common adjectives, nouns and pronouns were used. Looking at the result of the text processing, I created illustrated maps with the number of times these most common words were used.
|
||||||
|
|
@ -0,0 +1,569 @@
|
|||||||
|
# IMPORT
|
||||||
|
# to work with files in folder
|
||||||
|
import os
|
||||||
|
|
||||||
|
# to work with json files
|
||||||
|
import json
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
# to create the Flask app
|
||||||
|
from flask import Flask, render_template, request, url_for, redirect, jsonify, abort
|
||||||
|
|
||||||
|
# to import text contents and metadata from markdown files
|
||||||
|
from flaskext.markdown import Markdown
|
||||||
|
import frontmatter
|
||||||
|
|
||||||
|
# to cast string arguments into the required types
|
||||||
|
from pydoc import locate
|
||||||
|
|
||||||
|
# to work with notebooks
|
||||||
|
#
|
||||||
|
# to import notebook files
|
||||||
|
import nbimporter
|
||||||
|
nbimporter.options['only_defs'] = False
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
# to read and execute the content of notebooks
|
||||||
|
import nbformat
|
||||||
|
from nbconvert import HTMLExporter, MarkdownExporter
|
||||||
|
from nbconvert.preprocessors import ExecutePreprocessor
|
||||||
|
|
||||||
|
# not sure about this is in the nbconvert documentation
|
||||||
|
from traitlets.config import Config
|
||||||
|
|
||||||
|
# to work with placeholder descriptions
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
# Subgroup Projects import
|
||||||
|
|
||||||
|
# not really happy of this routing for the module but
|
||||||
|
ac = importlib.import_module("projects.annotation-compass.annotation_compass")
|
||||||
|
|
||||||
|
|
||||||
|
# FUNCTIONS
|
||||||
|
|
||||||
|
def filenames(folder, remove_ext = False):
|
||||||
|
''' Read all the functions in a folder '''
|
||||||
|
names = []
|
||||||
|
for entry in os.scandir(folder):
|
||||||
|
# add to the list only proper files
|
||||||
|
if entry.is_file(follow_symlinks=False):
|
||||||
|
# remove the extension from the filename
|
||||||
|
n = os.path.splitext(entry.name)[0]
|
||||||
|
if remove_ext:
|
||||||
|
n = entry.name
|
||||||
|
names.append(n)
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
def dirnames(folder):
|
||||||
|
''' Return all the folders in a folder '''
|
||||||
|
names = []
|
||||||
|
for entry in os.scandir(folder):
|
||||||
|
# add to the list only proper files
|
||||||
|
if not entry.name.startswith('.') and entry.is_dir():
|
||||||
|
# remove the extension from the filename
|
||||||
|
names.append(entry.name)
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
# not really sure about this file -> module -> function thing!
|
||||||
|
# could someone help pls ?
|
||||||
|
def get_function(name, folder):
|
||||||
|
''' Dynamic import a function from a folder '''
|
||||||
|
file = __import__(f'{folder}.{name}')
|
||||||
|
module = getattr(file, name)
|
||||||
|
function = getattr(module, name)
|
||||||
|
return function
|
||||||
|
|
||||||
|
|
||||||
|
def get_function_info(function):
|
||||||
|
''' Extract info from a function '''
|
||||||
|
name = function.__name__
|
||||||
|
description = function.__doc__
|
||||||
|
parameters = []
|
||||||
|
output = ''
|
||||||
|
|
||||||
|
# TODO: default values
|
||||||
|
|
||||||
|
# populate a list of tuple with patameter, type
|
||||||
|
for param in function.__annotations__.keys():
|
||||||
|
if param == 'return':
|
||||||
|
output = function.__annotations__[param].__name__
|
||||||
|
if param != 'return':
|
||||||
|
parameters.append((param, function.__annotations__[param].__name__))
|
||||||
|
|
||||||
|
return(name, description, parameters, output)
|
||||||
|
|
||||||
|
def print_info(function):
|
||||||
|
''' Print the info of a function nicely '''
|
||||||
|
name, description, parameters, output = get_function_info(function)
|
||||||
|
|
||||||
|
# very important feature
|
||||||
|
from kaomoji.kaomoji import Kaomoji
|
||||||
|
kao = Kaomoji()
|
||||||
|
|
||||||
|
header = f'----------{kao.create()}'
|
||||||
|
footer = '-' * len(header)
|
||||||
|
|
||||||
|
print(header)
|
||||||
|
print(name)
|
||||||
|
print(description)
|
||||||
|
print('Input:')
|
||||||
|
for param, tp in parameters:
|
||||||
|
print(f' {param}, of type {tp}')
|
||||||
|
print(f'Returns a {output}')
|
||||||
|
print(footer)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_function_list():
|
||||||
|
''' Build a list of the function '''
|
||||||
|
functions = []
|
||||||
|
for function in filenames("./notebooks"):
|
||||||
|
try:
|
||||||
|
fx = get_function(function, notebooks)
|
||||||
|
name, description, parameters, output = get_function_info(fx)
|
||||||
|
# print(f'{function} function is ok')
|
||||||
|
# print(f'Description is: {description}')
|
||||||
|
if description == None:
|
||||||
|
description = placeholder_description('function')
|
||||||
|
f = {
|
||||||
|
"title": name,
|
||||||
|
"description": description
|
||||||
|
}
|
||||||
|
except:
|
||||||
|
# print('--->error so placeholder fx')
|
||||||
|
f = {
|
||||||
|
"title": function,
|
||||||
|
"description": placeholder_description('function')
|
||||||
|
}
|
||||||
|
functions.append(f)
|
||||||
|
# print(functions)
|
||||||
|
with open('./static/functions.json', 'w') as file:
|
||||||
|
json.dump(functions, file)
|
||||||
|
|
||||||
|
|
||||||
|
def placeholder_description(subject):
|
||||||
|
''' Return a placeholder description of a subject '''
|
||||||
|
# ok this is a meme but is to make the notebooks a bit more waterproof
|
||||||
|
adjs = ['useful', 'nice', 'intresting', 'incredible', 'wow']
|
||||||
|
placeholders = [f'A super', f'A {choice(adjs)} and', f'You wont believe to this', f'Yet another' ]
|
||||||
|
return f'{choice(placeholders)} {choice(adjs)} {subject}'
|
||||||
|
|
||||||
|
|
||||||
|
# optionally you can pass a boolean argument to execute the notebook before the export
|
||||||
|
# but it is a slow process so by default is not active
|
||||||
|
# TODO: markdown export instead of HTML ?
|
||||||
|
# TODO: extract images from base64
|
||||||
|
def get_notebook_contents(filename, execute = False):
|
||||||
|
''' Export notebook contents as HTML. '''
|
||||||
|
with open(filename) as f:
|
||||||
|
nb = nbformat.read(f, as_version=4)
|
||||||
|
|
||||||
|
if execute:
|
||||||
|
ep = ExecutePreprocessor(timeout=600, kernel_name='python3')
|
||||||
|
ep.preprocess(nb, {'metadata':{'path':'notebooks/'}})
|
||||||
|
|
||||||
|
html_exporter = HTMLExporter()
|
||||||
|
html_exporter.template_name = 'basic'
|
||||||
|
(body, resources) = html_exporter.from_notebook_node(nb)
|
||||||
|
|
||||||
|
return body
|
||||||
|
|
||||||
|
# EXPORT AS MARKDOWN
|
||||||
|
def get_notebook_md(filename, execute = False):
|
||||||
|
''' Export notebook contents as Markdown. '''
|
||||||
|
with open(filename) as f:
|
||||||
|
nb = nbformat.read(f, as_version=4)
|
||||||
|
|
||||||
|
if execute:
|
||||||
|
ep = ExecutePreprocessor(timeout=600, kernel_name='python3')
|
||||||
|
ep.preprocess(nb, {'metadata':{'path':'notebooks/'}})
|
||||||
|
|
||||||
|
md_exporter = MarkdownExporter()
|
||||||
|
|
||||||
|
(body, resources) = md_exporter.from_notebook_node(nb)
|
||||||
|
|
||||||
|
return body
|
||||||
|
|
||||||
|
def get_contents(filename, directory = './contents'):
|
||||||
|
''' Return contents from a filename as frontmatter handler '''
|
||||||
|
with open(f"{directory}/{filename}", "r") as f:
|
||||||
|
content = frontmatter.load(f)
|
||||||
|
return content
|
||||||
|
|
||||||
|
def get_meta(filename, directory = './contents'):
|
||||||
|
''' Return contents from a filename as frontmatter handler '''
|
||||||
|
with open(f"{directory}/{filename}", "r") as f:
|
||||||
|
metadata, content = frontmatter.parse(f.read())
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
# EVENT MODE
|
||||||
|
|
||||||
|
def is_event_mode():
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# FLASK APP
|
||||||
|
|
||||||
|
base_url = "si16"
|
||||||
|
notebooks = "notebooks"
|
||||||
|
projects = "projects"
|
||||||
|
|
||||||
|
|
||||||
|
# create flask application
|
||||||
|
app = Flask(__name__,
|
||||||
|
static_url_path=f'/soupboat/{base_url}/static',
|
||||||
|
static_folder=f'/soupboat/{base_url}/static')
|
||||||
|
Markdown(app, extensions=['extra'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# add the base_url variable to all the flask templates
|
||||||
|
@app.context_processor
|
||||||
|
def set_base_url():
|
||||||
|
return dict(base_url = base_url)
|
||||||
|
|
||||||
|
# Generate functions list
|
||||||
|
generate_function_list()
|
||||||
|
|
||||||
|
# For specific pages we can build and link dedicated templates
|
||||||
|
|
||||||
|
|
||||||
|
# Homepage
|
||||||
|
@app.route(f"/{base_url}/")
|
||||||
|
def home_page():
|
||||||
|
|
||||||
|
# get the basic info of the website from the /contents/si16_info.md file
|
||||||
|
info = get_contents("si16_info.md").to_dict()
|
||||||
|
|
||||||
|
|
||||||
|
projects_list = []
|
||||||
|
for project in dirnames("./projects"):
|
||||||
|
page = get_contents("documentation.md", f"./{projects}/{project}").to_dict()
|
||||||
|
page['slug'] = project
|
||||||
|
projects_list.append(page)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# get the list of the projects, the functions, and the corpora
|
||||||
|
home = {
|
||||||
|
**info,
|
||||||
|
"projects": projects_list,
|
||||||
|
"functions": filenames("./notebooks"),
|
||||||
|
"corpora": dirnames("./static/corpora")
|
||||||
|
}
|
||||||
|
return render_template("home.html", **home)
|
||||||
|
|
||||||
|
|
||||||
|
# # About Page
|
||||||
|
# @app.route(f"/{base_url}/about/")
|
||||||
|
# def about_page():
|
||||||
|
# about = get_contents('about.md')
|
||||||
|
# return render_template("about.html", title = about['title'], description = about['description'], contents=about.content)
|
||||||
|
|
||||||
|
# For generic pages we can include a common template and change only the contents
|
||||||
|
@app.route(f"/{base_url}/<slug>/")
|
||||||
|
def dynamic_page(slug = None):
|
||||||
|
try:
|
||||||
|
page = get_contents(f"{slug}.md").to_dict()
|
||||||
|
# page is a dictionary that contains:
|
||||||
|
# - all the attributes in the markdown file (ex: title, description, soup, etc)
|
||||||
|
# - the content of the md in the property 'content'
|
||||||
|
# in this way we can access those frontmatter attributes in jinja simply using the variables title, description, soup, etc
|
||||||
|
return render_template("page.html", **page)
|
||||||
|
except FileNotFoundError:
|
||||||
|
# TODO: a proper not found page
|
||||||
|
return render_template('404.html')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# List of projects
|
||||||
|
@app.route(f"/{base_url}/projects/")
|
||||||
|
def projects_list():
|
||||||
|
# get a list of the functions from the notebooks folder
|
||||||
|
projects_list = []
|
||||||
|
for project in dirnames("./projects"):
|
||||||
|
page = get_contents("documentation.md", f"./{projects}/{project}").to_dict()
|
||||||
|
page['slug'] = project
|
||||||
|
projects_list.append(page)
|
||||||
|
|
||||||
|
info = get_contents("projects.md").to_dict()
|
||||||
|
|
||||||
|
# generate a link to each function
|
||||||
|
return render_template("projects.html", projects=projects_list, **info)
|
||||||
|
|
||||||
|
|
||||||
|
# Single project
|
||||||
|
@app.route(f"/{base_url}/projects/<project>/")
|
||||||
|
def p_info(project = None):
|
||||||
|
try:
|
||||||
|
|
||||||
|
page = get_contents("documentation.md", f"./{projects}/{project}").to_dict()
|
||||||
|
|
||||||
|
if 'showcases' in dirnames(f"./{projects}/{project}"):
|
||||||
|
page['showcases'] = []
|
||||||
|
showcases_list = filenames(f"./{projects}/{project}/showcases/")
|
||||||
|
for showcase in showcases_list:
|
||||||
|
print(showcase)
|
||||||
|
info = get_meta(showcase + '.md', f"./{projects}/{project}/showcases/")
|
||||||
|
info['slug'] = showcase
|
||||||
|
page['showcases'].append(info)
|
||||||
|
|
||||||
|
return render_template("project.html", **page)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return render_template('404.html')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/projects/<project>/<showcase>/")
|
||||||
|
def p_showcase(project = None, showcase = None):
|
||||||
|
print(project)
|
||||||
|
print(showcase)
|
||||||
|
try:
|
||||||
|
page = get_contents(f"{showcase}.md", f"./{projects}/{project}/showcases").to_dict()
|
||||||
|
return render_template('page.html', **page)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return render_template('404.html')
|
||||||
|
return render_template('404.html')
|
||||||
|
|
||||||
|
# List of functions
|
||||||
|
@app.route(f"/{base_url}/functions/")
|
||||||
|
def functions_list():
|
||||||
|
|
||||||
|
|
||||||
|
info = get_contents("functions.md").to_dict()
|
||||||
|
|
||||||
|
# get a list of the functions from the notebooks folder
|
||||||
|
functions = filenames("./notebooks")
|
||||||
|
|
||||||
|
with open('./static/functions.json', 'r') as file:
|
||||||
|
functions = json.load(file)
|
||||||
|
|
||||||
|
|
||||||
|
# generate a link to each function
|
||||||
|
return render_template("functions.html", functions=functions, **info)
|
||||||
|
|
||||||
|
|
||||||
|
# Single Function page
|
||||||
|
@app.route(f"/{base_url}/functions/<function>/")
|
||||||
|
def f_info(function=None):
|
||||||
|
if function in filenames(f"./{notebooks}"):
|
||||||
|
fx = get_function(function, notebooks)
|
||||||
|
name, description, parameters, output = get_function_info(fx)
|
||||||
|
|
||||||
|
# executing a notebook takes a lot of time mmm should we just send them without the results of the examples? or save it executed?
|
||||||
|
# documentation = get_notebook_contents(f"./{notebooks}/{function}.ipynb")
|
||||||
|
|
||||||
|
documentation = get_notebook_md(f"./{notebooks}/{function}.ipynb")
|
||||||
|
|
||||||
|
return render_template("function.html", title=name, description=description, parameters=parameters, output=output, documentation=documentation)
|
||||||
|
|
||||||
|
# TODO: meaningful error code return
|
||||||
|
else:
|
||||||
|
return render_template('404.html')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Function API page
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/api/<function>/")
|
||||||
|
def f_api(function=None):
|
||||||
|
if function in filenames(f"./{notebooks}"):
|
||||||
|
|
||||||
|
fx = get_function(function, notebooks)
|
||||||
|
name, description, parameters, output = get_function_info(fx)
|
||||||
|
|
||||||
|
query_params = []
|
||||||
|
for param, tp in parameters:
|
||||||
|
a = request.args.get(param)
|
||||||
|
# cast the type of the argument to the type that the function requires
|
||||||
|
if tp == "list":
|
||||||
|
a = request.args.getlist(param, type=str)
|
||||||
|
else:
|
||||||
|
tp = locate(tp)
|
||||||
|
a = tp(a)
|
||||||
|
# print(a)
|
||||||
|
query_params.append(a)
|
||||||
|
return fx(*query_params)
|
||||||
|
|
||||||
|
# TODO: meaningful error code return
|
||||||
|
return "mmmm there is no function with this name sorry"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: maybe the event mode could be a decorator ? to avoid the request from the client every time and instead just do it in the server ?
|
||||||
|
# EVENT MODE
|
||||||
|
import mimetypes
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/api/is-event-mode/")
|
||||||
|
def event_mode():
|
||||||
|
if is_event_mode():
|
||||||
|
event_path = '/static/event'
|
||||||
|
event = dirnames("./static/event")
|
||||||
|
page = request.values.get('page', '')
|
||||||
|
snippets = []
|
||||||
|
if page in event:
|
||||||
|
snippets = []
|
||||||
|
for entry in os.scandir(f".{event_path}/{page}"):
|
||||||
|
# add to the list only proper files
|
||||||
|
if entry.is_file(follow_symlinks=False):
|
||||||
|
snippet = {
|
||||||
|
"name": entry.name
|
||||||
|
}
|
||||||
|
|
||||||
|
ty, enc = mimetypes.guess_type(entry.name)
|
||||||
|
|
||||||
|
if 'text' in ty:
|
||||||
|
snippet['type'] = 'text'
|
||||||
|
with open(f".{event_path}/{page}/{entry.name}", 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
snippet['content'] = content
|
||||||
|
elif 'image' in ty:
|
||||||
|
snippet['type'] = 'image'
|
||||||
|
snippet['content'] = f"{event_path}/{page}/{entry.name}"
|
||||||
|
elif 'video' in ty:
|
||||||
|
snippet['type'] = 'video'
|
||||||
|
snippet['content'] = f"{event_path}/{page}/{entry.name}"
|
||||||
|
elif 'audio' in ty:
|
||||||
|
snippet['type'] = 'audio'
|
||||||
|
snippet['content'] = f"{event_path}/{page}/{entry.name}"
|
||||||
|
|
||||||
|
snippets.append(snippet)
|
||||||
|
return {"event": True, "snippets": snippets}
|
||||||
|
return {"event": True}
|
||||||
|
return {"event": False}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# PROJECTS API pages
|
||||||
|
# custom section ===========
|
||||||
|
# warning mothership reporting
|
||||||
|
# we will add here the custom endpoints for each subgroup project
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 2MB max for file upload (we can change this)
|
||||||
|
app.config['MAX_CONTENT_LENGTH'] = 2 * 1000 * 1000
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/annotation-compass/", methods=['GET','POST'])
|
||||||
|
def annotation_compass():
|
||||||
|
if request.method == 'POST':
|
||||||
|
# Upload new file
|
||||||
|
ac.upload_file(request)
|
||||||
|
images = ac.list_images()
|
||||||
|
return render_template('annotation-compass.html', title='Annotation Compass', images=images)
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/annotation-compass/annotate/<image>/")
|
||||||
|
def annotate_image(image=None):
|
||||||
|
print(app.static_url_path, app.static_folder)
|
||||||
|
description = ''
|
||||||
|
try:
|
||||||
|
description = ac.get_image_description(image)
|
||||||
|
except:
|
||||||
|
print('there is no description')
|
||||||
|
return render_template('annotate_image.html', image=image, description=description)
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/annotation-compass/add-label/", methods=['GET','POST'])
|
||||||
|
def insert_label():
|
||||||
|
if request.method == 'POST':
|
||||||
|
return ac.insert_label(request)
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/annotation-compass/get-labels/<image>/")
|
||||||
|
def get_labels_list(image=None):
|
||||||
|
return ac.get_labels_list(image)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# JIAN API
|
||||||
|
|
||||||
|
def generate_urls(elements):
|
||||||
|
a_list=''
|
||||||
|
for element in elements:
|
||||||
|
url=f'https://hub.xpub.nl/soupboat/individual-maps/{element}/'
|
||||||
|
a = f'<a href="{url}">{element}</a><br />'
|
||||||
|
a_list = a_list + a
|
||||||
|
return a_list
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/api/label/rejection/individual_map/")
|
||||||
|
def individual_map():
|
||||||
|
|
||||||
|
image = 'xpub1_rotterdam_map_1400px.jpg'
|
||||||
|
url = f"https://hub.xpub.nl/soupboat/generic-labels/get-labels/?image={image}"
|
||||||
|
response = urlopen(url)
|
||||||
|
data_json = json.loads(response.read())
|
||||||
|
|
||||||
|
all_userIDs = []
|
||||||
|
for label in data_json['labels']:
|
||||||
|
all_userIDs.append(label['userID'])
|
||||||
|
set_userIDs = set(all_userIDs)
|
||||||
|
|
||||||
|
im = get_function('individual_map', notebooks)
|
||||||
|
|
||||||
|
individual_labels = im(data_json['labels'], ['5058763759','5941298752'])
|
||||||
|
|
||||||
|
to_html = get_function('html_tag', notebooks)
|
||||||
|
result = to_html(individual_labels, True, True, True, True)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@app.route(f"/{base_url}/projects/map/rejection_map/")
|
||||||
|
def rejection_map():
|
||||||
|
return render_template('rejection_map.html')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ===============
|
||||||
|
# Error handlers!
|
||||||
|
@app.errorhandler(400)
|
||||||
|
def error_400(e):
|
||||||
|
# bad request or invalid url
|
||||||
|
return render_template('400.html'), 400
|
||||||
|
|
||||||
|
@app.errorhandler(403)
|
||||||
|
def error_403(e):
|
||||||
|
# forbidden (for invalid key) for evemt mode when it's not the 17th of the month
|
||||||
|
return render_template('403.html'), 403
|
||||||
|
|
||||||
|
@app.errorhandler(404)
|
||||||
|
def error_404(e):
|
||||||
|
# page not found
|
||||||
|
return render_template('404.html'), 404
|
||||||
|
|
||||||
|
@app.errorhandler(500)
|
||||||
|
def error_500(e):
|
||||||
|
# internal server error
|
||||||
|
return render_template('500.html'), 500
|
||||||
|
|
||||||
|
@app.errorhandler(502)
|
||||||
|
def error_502(e):
|
||||||
|
# bad gateaway
|
||||||
|
return render_template('502.html'), 502
|
||||||
|
|
||||||
|
@app.errorhandler(503)
|
||||||
|
def error_503(e):
|
||||||
|
# service temporarily unavailable, for secret breaks
|
||||||
|
return render_template('503.html'), 503
|
||||||
|
|
||||||
|
@app.errorhandler(504)
|
||||||
|
def error_503(e):
|
||||||
|
# ???????? gateway timeout shall we put it?????
|
||||||
|
return render_template('504.html'), 504
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# RUN
|
||||||
|
|
||||||
|
app.run(port="3131")
|
@ -0,0 +1 @@
|
|||||||
|
{"functions": [{"title": "vernacular_map", "description": "A nice and intresting function"}, {"title": "text_file_to_blob", "description": null}, {"title": "shout", "description": "Repeat the vowels in a string for a specified number of times"}, {"title": "reverse", "description": "Reverse the input sentence by sentence"}, {"title": "cocktail_generator", "description": "randomly chooses ingredients from a menu for a nice cocktail recipe"}, {"title": "blob_to_excerpts_list", "description": null}, {"title": "respell", "description": null}, {"title": "mashup", "description": null}, {"title": "reveal", "description": null}, {"title": "repeat", "description": "Repeat a string for a specified number of times"}, {"title": "highlight_map", "description": "A nice and intresting function"}, {"title": "individual_map", "description": "You wont believe to this function"}, {"title": "bridge", "description": "You wont believe to this function"}, {"title": "add_target_info", "description": null}, {"title": "area_map", "description": "A super useful function"}, {"title": "stich", "description": null}, {"title": "input-back-to-text", "description": "You wont believe to this function"}, {"title": "target_map", "description": "A super useful function"}, {"title": "ghost_map", "description": "A nice and intresting function"}, {"title": "html_tag", "description": "A super useful function"}]}
|
@ -0,0 +1,233 @@
|
|||||||
|
h3,
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io,
|
||||||
|
.endpoints,
|
||||||
|
.playground {
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground,
|
||||||
|
.playground-input,
|
||||||
|
.playground-output,
|
||||||
|
.notebook {
|
||||||
|
grid-column: -1 / 1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
grid-column-gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
place-items: start;
|
||||||
|
grid-gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io > * {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io .input,
|
||||||
|
.function-io .output,
|
||||||
|
.playground .input {
|
||||||
|
background-color: white;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io ul {
|
||||||
|
font-family: "Necto";
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints code {
|
||||||
|
background-color: white;
|
||||||
|
margin: 30px 0;
|
||||||
|
white-space: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints .example {
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playgroud-input .input {
|
||||||
|
grid-column: 1 / span 1;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground-output .output {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
min-height: calc(var(--text) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground * + label {
|
||||||
|
margin-top: 24px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground input[type="submit"] {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .notebook code {
|
||||||
|
position: relative;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.prettyprint.prettyprinted {
|
||||||
|
border: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.prettyprint.prettyprinted::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 460px;
|
||||||
|
height: 460px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.notebook {
|
||||||
|
width: 100%;
|
||||||
|
/* margin-top: 60px; */
|
||||||
|
/* padding-top: 60px; */
|
||||||
|
/* border-top: 1px solid currentColor; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook h1::before {
|
||||||
|
content: "Documentation: ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook p {
|
||||||
|
grid-column: span 2;
|
||||||
|
text-indent: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
grid-gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook .language-python {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
white-space: pre;
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
z-index: 100;
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook .language-python::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
top: 0;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: white;
|
||||||
|
mix-blend-mode: color;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook h1 {
|
||||||
|
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.notebook p {
|
||||||
|
margin: 30px 0;
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook p img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook code {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
align-self: flex-start;
|
||||||
|
background-color: white;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook h2 {
|
||||||
|
grid-column: 1/-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook img {
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook > * + * {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.playground,
|
||||||
|
.playground-input,
|
||||||
|
.playground-output,
|
||||||
|
.notebook,
|
||||||
|
.function-io,
|
||||||
|
.notebook pre {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io .input,
|
||||||
|
.function-io .output,
|
||||||
|
.playground .input {
|
||||||
|
background: none;
|
||||||
|
aspect-ratio: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground-output {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-content > * + * {
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook .language-python {
|
||||||
|
min-height: 300px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
.sticker {
|
||||||
|
font-size: var(--text);
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index {
|
||||||
|
margin: calc(var(--app-margin) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet + .sheet {
|
||||||
|
margin-top: var(--app-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet h3 a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.negative {
|
||||||
|
position: relative;
|
||||||
|
/* visibility: hidden; */
|
||||||
|
color: rgba(0,0,0,0.2);
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 48px;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
background-color: rgba(0, 0, 0, 0.075);
|
||||||
|
/* background-color: var(--background); */
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 3px 12px;
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .negative:after {
|
||||||
|
visibility: visible;
|
||||||
|
content: "";
|
||||||
|
background-color: rgba(0, 0, 0, 0.075);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
} */
|
||||||
|
|
||||||
|
.sheet > p {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.negative {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta > h2 {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet .section {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
|
||||||
|
font-size: var(--title);
|
||||||
|
color: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-link {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000;
|
||||||
|
top: 60px;
|
||||||
|
right: 60px;
|
||||||
|
|
||||||
|
background-color: springgreen;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 0 12px;
|
||||||
|
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
transform: scale(1);
|
||||||
|
transition: transform 0.2s ease-in;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-link:hover{
|
||||||
|
transition: transform 0.1s ease-out;
|
||||||
|
transform: scale(1.025);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
:root {
|
||||||
|
--background: white!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble + .bubble {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble:nth-child(2n + 2) {
|
||||||
|
/* background-color: var(--orange); */
|
||||||
|
grid-column-start: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p.bubble {
|
||||||
|
grid-column-start: 2;
|
||||||
|
margin: 30px 0;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
text-indent: 0;
|
||||||
|
justify-self: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p.intro {
|
||||||
|
text-indent: 0;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Courier New';
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: rgb(180, 180, 180) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background-color: rgba(0, 150, 255, 0.6);
|
||||||
|
text-shadow: 0 0 0px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.lowlight {
|
||||||
|
background-color: rgba(0, 0, 255, 0);
|
||||||
|
color: black;
|
||||||
|
text-shadow: 0 0 0px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ghost {
|
||||||
|
color: black;
|
||||||
|
text-shadow: 0 0 0px black;
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.page--content pre {
|
||||||
|
grid-column: span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.page--content h2 {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content h2:first-of-type{
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content h3 {
|
||||||
|
grid-column: 1 / span 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content ul,
|
||||||
|
.page--content ol {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content li {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.page--content p {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p img {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
.page--content .project-link {
|
||||||
|
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
place-self: center;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
margin: 60px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-link:hover{
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content .description {
|
||||||
|
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content pre {
|
||||||
|
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--header header{
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p img {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
.page--content p:first-of-type {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
@import url("/static/font/font.css");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--blue: #9edae2;
|
||||||
|
--pink: #f7d8e8;
|
||||||
|
--orange: #ffc496;
|
||||||
|
--yellow: #f9f5b0;
|
||||||
|
--green: #9fd3a8;
|
||||||
|
|
||||||
|
--content-width: 1440px;
|
||||||
|
--radius: 12px;
|
||||||
|
--background: var(--yellow);
|
||||||
|
--font: "Pirelli";
|
||||||
|
--title: 36px;
|
||||||
|
--text: 24px;
|
||||||
|
--app-margin: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
:root {
|
||||||
|
--app-margin: 18px;
|
||||||
|
--text: 21px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
.cards{
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
/* display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between; */
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
grid-gap: var(--app-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image{
|
||||||
|
word-break: break-all;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards .card-image .thumb {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
object-fit: contain;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
|
||||||
|
.cards {
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image{
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards .card-image .thumb {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 0;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
.cards{
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
/* display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between; */
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
grid-gap: var(--app-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image{
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image{
|
||||||
|
word-break: break-all;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards .card-image .thumb {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
object-fit: contain;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
|
||||||
|
.cards {
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-image{
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cards .card-image .thumb {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 0;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,322 @@
|
|||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Courier New';
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: grey ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.red {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blur {
|
||||||
|
text-shadow: 0 0 8px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red-blur {
|
||||||
|
color: red;
|
||||||
|
text-shadow: 0 0 8px red;
|
||||||
|
text-decoration: underline;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-color {
|
||||||
|
background-color: rgba(255, 0, 0, 0.6);
|
||||||
|
text-shadow: 0 0 8px black;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.test-form {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
border: 1px solid tomato;
|
||||||
|
opacity: 0.5;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor.can-draw {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor.show-editor {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary {
|
||||||
|
background: none;
|
||||||
|
/* border: 1px dashed tomato; */
|
||||||
|
box-shadow: none;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary form {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 1ch;
|
||||||
|
border: none;
|
||||||
|
background-color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary textarea:focus {
|
||||||
|
outline: 1px dashed tomato;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary button {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary button + button {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary .label--number,
|
||||||
|
.label.temporary .label--close {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label--number {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label--close {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
background: none;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.label--text {
|
||||||
|
margin: 1ch 0;
|
||||||
|
padding: 0 1ch;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-input {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 200;
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
background-color: rgba(255, 99, 71, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-input.visible {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
padding: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal input {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal input:focus {
|
||||||
|
outline: none;
|
||||||
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-input button {
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cancel {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-container {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-container img {
|
||||||
|
max-width: 70w;
|
||||||
|
max-height: 70vh;
|
||||||
|
object-fit: contain;
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-container img.visible {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info,
|
||||||
|
.transcription {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 50;
|
||||||
|
|
||||||
|
padding: 24px;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
width: 25%;
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
background-color: #111;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
transform: translateX(100%);
|
||||||
|
transition: transform 0.4s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcription.active,
|
||||||
|
.info.active {
|
||||||
|
transform: translateX(0);
|
||||||
|
transition: transform 0.6s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcription .title,
|
||||||
|
.info .title {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcription ol {
|
||||||
|
padding: 0;
|
||||||
|
list-style-position: inside;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#show-info,
|
||||||
|
#show-transcription,
|
||||||
|
.close,
|
||||||
|
button {
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
|
||||||
|
color: tomato;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#show-transcription:hover,
|
||||||
|
#show-info:hover {
|
||||||
|
border: 1px solid tomato;
|
||||||
|
background-color: tomato;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
right: 24px;
|
||||||
|
top: 32px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#export-text:hover,
|
||||||
|
.close:hover {
|
||||||
|
border: 1px solid white;
|
||||||
|
background-color: white;
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
#export-text {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 50;
|
||||||
|
|
||||||
|
padding: 24px;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav > * {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
@ -0,0 +1,337 @@
|
|||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-form {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 90vw;
|
||||||
|
height: 90vh;
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
border: 1px solid tomato;
|
||||||
|
opacity: 0.5;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 150;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor.can-draw {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor.show-editor {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
position: absolute;
|
||||||
|
background-color: rgba(250, 99, 72, 0.2);
|
||||||
|
/* border: 1px solid currentColor; */
|
||||||
|
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary {
|
||||||
|
background: none;
|
||||||
|
/* border: 1px dashed tomato; */
|
||||||
|
box-shadow: none;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary form {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary textarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 1ch;
|
||||||
|
border: none;
|
||||||
|
background-color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary textarea:focus {
|
||||||
|
outline: 1px dashed tomato;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary button {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary button + button {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label.temporary .label--number,
|
||||||
|
.label.temporary .label--close {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label--number {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label--close {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
background: none;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.label--text {
|
||||||
|
margin: 1ch 0;
|
||||||
|
padding: 0 1ch;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow-y: auto;
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-input {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 200;
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
background-color: rgba(255, 99, 71, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-input.visible {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal input {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal input:focus {
|
||||||
|
outline: none;
|
||||||
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-input button {
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cancel {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#target {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-container img {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
object-fit: contain;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
position: relative;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.background-container img.visible {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info,
|
||||||
|
.transcription {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 50;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
width: min(50%, 600px);
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
background-color: #111;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
transform: translateX(100%);
|
||||||
|
transition: transform 0.4s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info .contents,
|
||||||
|
.transcription .contents {
|
||||||
|
padding: 24px;
|
||||||
|
height: 100vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contents p {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcription.active,
|
||||||
|
.info.active {
|
||||||
|
transform: translateX(0);
|
||||||
|
transition: transform 0.6s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcription .title,
|
||||||
|
.info .title {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcription ol {
|
||||||
|
padding: 0;
|
||||||
|
list-style-position: inside;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
margin-bottom: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#show-info,
|
||||||
|
#show-transcription,
|
||||||
|
.close,
|
||||||
|
button {
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
|
||||||
|
color: tomato;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#show-transcription:hover,
|
||||||
|
#show-info:hover {
|
||||||
|
border: 1px solid tomato;
|
||||||
|
background-color: tomato;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
right: 24px;
|
||||||
|
top: 32px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#export-text:hover,
|
||||||
|
.close:hover {
|
||||||
|
border: 1px solid white;
|
||||||
|
background-color: white;
|
||||||
|
color: #111;
|
||||||
|
}
|
||||||
|
|
||||||
|
#export-text {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 50;
|
||||||
|
|
||||||
|
padding: 24px;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav > * {
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcription .options {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
@ -0,0 +1,233 @@
|
|||||||
|
h3,
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io,
|
||||||
|
.endpoints,
|
||||||
|
.playground {
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground,
|
||||||
|
.playground-input,
|
||||||
|
.playground-output,
|
||||||
|
.notebook {
|
||||||
|
grid-column: -1 / 1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
grid-column-gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
place-items: start;
|
||||||
|
grid-gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io > * {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io .input,
|
||||||
|
.function-io .output,
|
||||||
|
.playground .input {
|
||||||
|
background-color: white;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io ul {
|
||||||
|
font-family: "Necto";
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints code {
|
||||||
|
background-color: white;
|
||||||
|
margin: 30px 0;
|
||||||
|
white-space: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints .example {
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playgroud-input .input {
|
||||||
|
grid-column: 1 / span 1;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground-output .output {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
min-height: calc(var(--text) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground * + label {
|
||||||
|
margin-top: 24px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground input[type="submit"] {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .notebook code {
|
||||||
|
position: relative;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.prettyprint.prettyprinted {
|
||||||
|
border: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.prettyprint.prettyprinted::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 460px;
|
||||||
|
height: 460px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.notebook {
|
||||||
|
width: 100%;
|
||||||
|
/* margin-top: 60px; */
|
||||||
|
/* padding-top: 60px; */
|
||||||
|
/* border-top: 1px solid currentColor; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook h1::before {
|
||||||
|
content: "Documentation: ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook p {
|
||||||
|
grid-column: span 2;
|
||||||
|
text-indent: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
grid-gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook .language-python {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
white-space: pre;
|
||||||
|
background: none;
|
||||||
|
padding: 0;
|
||||||
|
z-index: 100;
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook .language-python::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
top: 0;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: white;
|
||||||
|
mix-blend-mode: color;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook h1 {
|
||||||
|
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.notebook p {
|
||||||
|
margin: 30px 0;
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook p img {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook code {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
align-self: flex-start;
|
||||||
|
background-color: white;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook h2 {
|
||||||
|
grid-column: 1/-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook img {
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook > * + * {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
.playground,
|
||||||
|
.playground-input,
|
||||||
|
.playground-output,
|
||||||
|
.notebook,
|
||||||
|
.function-io,
|
||||||
|
.notebook pre {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-io .input,
|
||||||
|
.function-io .output,
|
||||||
|
.playground .input {
|
||||||
|
background: none;
|
||||||
|
aspect-ratio: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playground-output {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-content > * + * {
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook .language-python {
|
||||||
|
min-height: 300px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
.sticker {
|
||||||
|
font-size: var(--text);
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index {
|
||||||
|
margin: calc(var(--app-margin) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet + .sheet {
|
||||||
|
margin-top: var(--app-margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet h3 a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.negative {
|
||||||
|
position: relative;
|
||||||
|
/* visibility: hidden; */
|
||||||
|
color: rgba(0,0,0,0.2);
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 48px;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
background-color: rgba(0, 0, 0, 0.075);
|
||||||
|
/* background-color: var(--background); */
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 3px 12px;
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .negative:after {
|
||||||
|
visibility: visible;
|
||||||
|
content: "";
|
||||||
|
background-color: rgba(0, 0, 0, 0.075);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.sheet > p {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.negative {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta > h2 {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sheet .section {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
|
||||||
|
font-size: var(--title);
|
||||||
|
color: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-link {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1000;
|
||||||
|
top: 60px;
|
||||||
|
right: 60px;
|
||||||
|
|
||||||
|
background-color: springgreen;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 0 12px;
|
||||||
|
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
transform: scale(1);
|
||||||
|
transition: transform 0.2s ease-in;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.chat-link:hover{
|
||||||
|
transition: transform 0.1s ease-out;
|
||||||
|
transform: scale(1.025);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
:root {
|
||||||
|
--background: white!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble + .bubble {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble:nth-child(2n + 2) {
|
||||||
|
/* background-color: var(--orange); */
|
||||||
|
grid-column-start: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p.bubble {
|
||||||
|
grid-column-start: 2;
|
||||||
|
margin: 30px 0;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
text-indent: 0;
|
||||||
|
justify-self: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p.intro {
|
||||||
|
text-indent: 0;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Courier New';
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: rgb(180, 180, 180) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background-color: rgba(0, 150, 255, 0.6);
|
||||||
|
text-shadow: 0 0 0px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.lowlight {
|
||||||
|
background-color: rgba(0, 0, 255, 0);
|
||||||
|
color: black;
|
||||||
|
text-shadow: 0 0 0px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ghost {
|
||||||
|
color: black;
|
||||||
|
text-shadow: 0 0 0px black;
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
.list {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
position: relative;
|
||||||
|
border-top: 1px solid currentColor;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
grid-gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:last-of-type {
|
||||||
|
padding-bottom: 24px;
|
||||||
|
border-bottom: 1px solid currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.description {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
padding-right: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.link {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767.98px) {
|
||||||
|
table,
|
||||||
|
tr,
|
||||||
|
td {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr + tr {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.title {
|
||||||
|
padding-right: 30px;
|
||||||
|
margin-top: 18px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.description {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.link {
|
||||||
|
top: 18px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
body {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.page--header {
|
||||||
|
width: auto;
|
||||||
|
top: 45px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.sections {
|
||||||
|
margin-top: 30vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
color: var(--textcolor);
|
||||||
|
row-gap:4vh;
|
||||||
|
}
|
||||||
|
.section {
|
||||||
|
position:relative
|
||||||
|
}
|
||||||
|
.reporter {
|
||||||
|
align-self: flex-start;
|
||||||
|
width: 70vw;
|
||||||
|
}
|
||||||
|
.answer {
|
||||||
|
align-self: flex-end;
|
||||||
|
width: 70vw;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
.reporter{
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.answer{
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
// Get the button, and when the user clicks on it, execute myFunction
|
||||||
|
//document.getElementById("info-btn").onclick = function() {showInfo()};
|
||||||
|
|
||||||
|
/* myFunction toggles between adding and removing the show class, which is used to hide and show the dropdown content */
|
||||||
|
function showInfo() {
|
||||||
|
document.getElementById("info").classList.toggle("show");
|
||||||
|
}
|
@ -0,0 +1,270 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: Pirelli;
|
||||||
|
src: url("./font/pirelli-regular.woff");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Pirelli;
|
||||||
|
src: url("./font/pirelli-bolditalic.woff");
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Necto-Mono;
|
||||||
|
src: url("./font/Necto-Mono.woff");
|
||||||
|
}
|
||||||
|
:root {
|
||||||
|
--red: tomato;
|
||||||
|
--background: rgb(233, 233, 233);
|
||||||
|
--textcolor: rgb(39, 39, 39);
|
||||||
|
--blue: #9edae2;
|
||||||
|
--pink: #f7d8e8;
|
||||||
|
--orange: #ffc496;
|
||||||
|
--yellow: #f9f5b0;
|
||||||
|
--green: #9fd3a8;
|
||||||
|
|
||||||
|
--content-width: 1440px;
|
||||||
|
--radius: 12px;
|
||||||
|
--font: "Pirelli";
|
||||||
|
--title: 36px;
|
||||||
|
--text: 24px;
|
||||||
|
--app-margin: 30px;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: Pirelli;
|
||||||
|
background-color: var(--background);
|
||||||
|
color: var(--textcolor);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
a.goto-archive {
|
||||||
|
position: fixed;
|
||||||
|
top: 16px;
|
||||||
|
right: 16px;
|
||||||
|
color: var(--red);
|
||||||
|
font-size: 1.2em;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.page--header {
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
margin: 8vh 0;
|
||||||
|
padding: 0 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
column-gap: 8px;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-content: center;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.page--header > * {
|
||||||
|
border: solid 1px var(--red);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: var(--background);
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 36px;
|
||||||
|
color: var(--red);
|
||||||
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question {
|
||||||
|
display: flex;
|
||||||
|
font-size: 1.2em;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
row-gap: 24px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 28vh;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
/*background-color: white;*/
|
||||||
|
display: none;
|
||||||
|
padding: 16px;
|
||||||
|
border: solid 1px var(--red);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--red);
|
||||||
|
font-size: 1em;
|
||||||
|
flex-basis: 35%;
|
||||||
|
}
|
||||||
|
.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.q-text {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
flex-basis: 65%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*styling of form*/
|
||||||
|
form {
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: wrap;
|
||||||
|
column-gap: 24px;
|
||||||
|
row-gap: 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.form-box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 8px;
|
||||||
|
flex-basis: 30%;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.form-box#apply {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
resize: none;
|
||||||
|
/* font-family: Necto-mono; */
|
||||||
|
border-radius: 4px;
|
||||||
|
border: solid 1px grey;
|
||||||
|
transition: border-radius 70ms ease-in-out;
|
||||||
|
}
|
||||||
|
/* when the cursor is iside the text area*/
|
||||||
|
textarea:focus {
|
||||||
|
border: solid 2px var(--red);
|
||||||
|
outline: none;
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-family: Pirelli;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
input:hover {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
/*to pick the exact type of input you wanna style use "[]"*/
|
||||||
|
input[type="radio"] {
|
||||||
|
font-family: Pirelli;
|
||||||
|
background-color: var(--red);
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*custom radio button*/
|
||||||
|
/* The container */
|
||||||
|
.radio-label {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 35px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.2em;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
/* Hide the browser's default radio button */
|
||||||
|
.radio-label input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a custom radio button */
|
||||||
|
.checkmark {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 24px;
|
||||||
|
width: 24px;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
border: solid 2px var(--red);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On mouse-over change color */
|
||||||
|
.radio-label:hover {
|
||||||
|
color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the radio button is checked, add a blue background */
|
||||||
|
.radio-label input:checked ~ .checkmark {
|
||||||
|
background-color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the indicator (the dot/circle - hidden when not checked) */
|
||||||
|
.checkmark:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lbl-result {
|
||||||
|
color: grey;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
.result {
|
||||||
|
font-family: Courier;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-end {
|
||||||
|
margin: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-flow: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
align-content: stretch;
|
||||||
|
column-gap: 8px;
|
||||||
|
}
|
||||||
|
.form-end > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-basis: 50%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
a.goto-form {
|
||||||
|
border: solid 1px rgb(107, 107, 107);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: Pirelli;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1.2em;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--textcolor);
|
||||||
|
text-align: center;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
.goto-form:hover {
|
||||||
|
color: var(--red);
|
||||||
|
background-color: rgb(216, 216, 216);
|
||||||
|
}
|
||||||
|
.save-btn {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
:root {
|
||||||
|
--app-margin: 18px;
|
||||||
|
--text: 21px;
|
||||||
|
}
|
||||||
|
.title,
|
||||||
|
nav.h1 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.page--content pre {
|
||||||
|
grid-column: span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.page--content h2 {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content h2:first-of-type{
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content h3 {
|
||||||
|
grid-column: 1 / span 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content ul,
|
||||||
|
.page--content ol {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content li {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.page--content p {
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p img {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
.page--content .project-link {
|
||||||
|
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
place-self: center;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid currentColor;
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
margin: 60px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-link:hover{
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content .description {
|
||||||
|
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content pre {
|
||||||
|
|
||||||
|
grid-column: 2 / span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--header header{
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.page--content p img {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
.page--content p:first-of-type {
|
||||||
|
grid-column: 1 / span 2;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
@import url("/static/font/font.css");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--blue: #9edae2;
|
||||||
|
--pink: #f7d8e8;
|
||||||
|
--orange: #ffc496;
|
||||||
|
--yellow: #f9f5b0;
|
||||||
|
--green: #9fd3a8;
|
||||||
|
|
||||||
|
--content-width: 1440px;
|
||||||
|
--radius: 12px;
|
||||||
|
--background: var(--yellow);
|
||||||
|
--font: "Pirelli";
|
||||||
|
--title: 36px;
|
||||||
|
--text: 24px;
|
||||||
|
--app-margin: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 991.98px) {
|
||||||
|
:root {
|
||||||
|
--app-margin: 18px;
|
||||||
|
--text: 21px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"cells": [],
|
||||||
|
"metadata": {},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "817008c8-6cc9-4e39-9ec0-b73785756099",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Upss I am having a break right now, cuddling my cat."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a39983dd-f828-499b-9e30-39ec45c056a1",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"I wasn't ready for this connection.\n",
|
||||||
|
"I am a bit moody right now, so I am concentrating on finding my center."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "3b79c6c1-c81a-459d-abbc-2a36bda652b8",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Ah! you are here! I wasn't excepting of you! Wait to put something on me"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "00670416-1257-442e-b55c-2a93b87f5931",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"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.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
drink drink glu glu
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
drink drink glu glu
|
@ -0,0 +1 @@
|
|||||||
|
Hello this is the event mode
|
@ -0,0 +1 @@
|
|||||||
|
We ate artichockes
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue