Browse Source

implementing changes after feedback

english-french
manetta 6 years ago
parent
commit
67f1e5a07d
  1. 2
      escpos.py
  2. 2
      manifestos.py
  3. 9
      printer.py
  4. 4
      readings.py
  5. 30
      start.py
  6. BIN
      static/css/fonts/go-mono/Go-Mono-Bold-Italic.ttf
  7. BIN
      static/css/fonts/go-mono/Go-Mono-Bold.ttf
  8. BIN
      static/css/fonts/go-mono/Go-Mono-Italic.ttf
  9. BIN
      static/css/fonts/go-mono/Go-Mono.ttf
  10. 36
      static/css/fonts/go-mono/README
  11. BIN
      static/css/fonts/unifont-11.0.03.ttf
  12. 92
      static/css/stylesheet.css
  13. BIN
      static/favicon.ico
  14. 38
      templates/en/about.html
  15. 6
      templates/en/base.html
  16. 49
      templates/en/index.html
  17. 3
      templates/en/manifesto.html
  18. 11
      templates/en/mappings-name.html
  19. 52
      templates/en/results.html
  20. 38
      templates/fr/about.html
  21. 8
      templates/fr/base.html
  22. 47
      templates/fr/index.html
  23. 11
      templates/fr/manifesto.html
  24. 10
      templates/fr/mappings-name.html
  25. 50
      templates/fr/results.html
  26. 27
      templates/fr/results_lists.html
  27. 50
      tfidf.top50.txt

2
escpos.py

@ -5,6 +5,8 @@
escpos = {
"init_printer": "\x1B\x40",
"select_international_character_set": "\x1B\x52\x00",
"justify_left": "\x1B\x61\x00",
"justify_center": "\x1B\x61\x01",
"justify_right": "\x1B\x61\x02",

2
manifestos.py

@ -31,5 +31,5 @@ manifestos = {
'2018_Purple_Noise_Manifesto_[EN]' : 'https://www.obn.org/purplenoise/wp-content/uploads/2019/02/Manifesto18FEB2019.pdf',
'2019_Cyberwitches_Manifesto_[EN]' : 'http://lucilehaute.fr/cyberwitches-manifesto/cyberwitches-manifesto-en.html',
'2019_Cyberwitches_Manifesto_[FR]' : 'http://lucilehaute.fr/cyberwitches-manifesto/cyberwitches-manifesto.html',
'2019_The_Call_for_Feminist_Data_[EN]' : 'https://vvvvvvaria.org/~mb/techfem/feminist_manifesto_large.pdf'
'2018_The_Call_for_Feminist_Data_[EN]' : 'https://vvvvvvaria.org/~mb/techfem/feminist_manifesto_large.pdf'
}

9
printer.py

@ -44,6 +44,7 @@ def printNow(query, results):
if connected == True:
print(escpos['reset'], file=stdout, flush=True)
print(escpos['init_printer'], file=stdout, flush=True)
print(escpos['select_international_character_set'], file=stdout, flush=True)
print(escpos['margin_left'], file=stdout, flush=True)
print(escpos['justify_center'], file=stdout, flush=True)
@ -73,19 +74,19 @@ def printNow(query, results):
print(linebreak, file=stdout, flush=True) # print line break ascii art
print('\n', file=stdout, flush=True)
title = insert_linebreaks(document['name'], 46)
print(escpos['normalfont'], title, file=stdout, flush=True) # print the document name
print(title, file=stdout, flush=True) # print the document name
print('\n', file=stdout, flush=True)
# start of sentence
part = insert_linebreaks(part, 21)
print(escpos['largefont'], part, escpos['bold'], file=stdout, flush=True) # print current part of sentence
part = insert_linebreaks(part, 46)
print(part, escpos['bold'], file=stdout, flush=True) # print current part of sentence
if i + 1 != len(sentence_splitted): # if this part is not the last one
print(match, escpos['reset'], file=stdout, flush=True) # print query
# line breaker after each sentence
if i + 1 == len(sentence_splitted):
print('\n | \n', escpos['normalfont'], file=stdout, flush=True)
print('\n | \n', file=stdout, flush=True)
sleep(3)
print(escpos['paperfeed_1l'], file=stdout, flush=True)

4
readings.py

@ -154,7 +154,7 @@ def request_results(query):
# (sentences, tfidf value, manifesto name)
x = 0
for tfidf, manifesto in order:
print('\n---', manifesto, '---')
# print('\n---', manifesto, '---')
results[x] = {}
results[x]['name'] = index[manifesto]['name'] # nicely readable name
results[x]['filename'] = manifesto
@ -176,7 +176,7 @@ def request_results(query):
# Append sentence to final set of matching results
results[x]['matches'].append(sentence)
print('Matching sentence:', sentence.replace('\n', ' '))
# print('Matching sentence:', sentence.replace('\n', ' '))
# Transform sentence into an HTML elements
html = insert_query_highlight(query, sentence, r, g, b)

30
start.py

@ -3,7 +3,7 @@
import os, sys
from sys import stdout
import flask
from flask import request, redirect
from flask import request, redirect, send_from_directory
import tfidf
import readings
import printer
@ -62,10 +62,17 @@ def index_lang(lang):
index = readings.load_index()
filenames = [manifesto for manifesto, _ in index.items()]
suggestions = open('words.txt', 'r').readlines()
mappings = readings.request_mappings_all()
mappings_top = [[tfidf, word] for manifesto, words in mappings.items() for tfidf, word in words]
mappings_top.sort(reverse=True)
return flask.render_template(lang+'/index.html', filenames=filenames, suggestions=suggestions, mappings=mappings_top[:100], lang=lang)
mappings_top = open('tfidf.top50.txt', 'r').readlines()
return flask.render_template(lang+'/index.html', filenames=filenames, suggestions=suggestions, mappings=mappings_top, lang=lang)
@APP.route('/<lang>/about', methods=['GET', 'POST'])
def about(lang):
"""
Displays the about page accessible at '/<lang>/about'.
"""
index = readings.load_index()
filenames = sorted([manifesto for manifesto, _ in index.items()])
return flask.render_template(lang+'/about.html', filenames=filenames, lang=lang)
@APP.route('/<lang>/manifesto/<name>', methods=['GET', 'POST'])
def manifesto(lang, name):
@ -97,17 +104,12 @@ def contrast_mappings_name(lang, name):
mappings, filenames = readings.request_mappings(name)
return flask.render_template(lang+'/mappings-name.html', filenames=filenames, mappings=mappings[name], manifesto=name, lang=lang)
@APP.route('/<lang>/colophon', methods=['GET', 'POST'])
def colophon(lang):
"""
Displays colophon page.
"""
index = readings.load_index()
filenames = sorted([manifesto for manifesto, _ in index.items()])
return flask.render_template(lang+'/colophon.html', filenames=filenames, lang=lang)
@APP.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(APP.root_path, 'static'), 'favicon.ico')
if __name__ == '__main__':
if not 'index.json' in os.listdir('.'):
tfidf.create_index()
# APP.debug=True
APP.debug=True
APP.run()

BIN
static/css/fonts/go-mono/Go-Mono-Bold-Italic.ttf

Binary file not shown.

BIN
static/css/fonts/go-mono/Go-Mono-Bold.ttf

Binary file not shown.

BIN
static/css/fonts/go-mono/Go-Mono-Italic.ttf

Binary file not shown.

BIN
static/css/fonts/go-mono/Go-Mono.ttf

Binary file not shown.

36
static/css/fonts/go-mono/README

@ -0,0 +1,36 @@
These fonts were created by the Bigelow & Holmes foundry specifically for the
Go project. See https://blog.golang.org/go-fonts for details.
They are licensed under the same open source license as the rest of the Go
project's software:
Copyright (c) 2016 Bigelow & Holmes Inc.. All rights reserved.
Distribution of this font is governed by the following license. If you do not
agree to this license, including the disclaimer, do not distribute or modify
this font.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Google Inc. nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

BIN
static/css/fonts/unifont-11.0.03.ttf

Binary file not shown.

92
static/css/stylesheet.css

@ -1,10 +1,20 @@
@font-face{
font-family: 'unifont';
src:url('fonts/unifont-11.0.03.ttf');
font-family: 'mono';
src:url('fonts/go-mono/Go-Mono.ttf');
font-style: normal;
font-weight: normal;
}
@font-face{
font-family: 'mono';
src:url('fonts/go-mono/Go-Mono-Italic.ttf');
font-style: italic;
font-weight: normal;
}
@font-face{
font-family: 'script';
src:url('fonts/LiberationSansNarrow-Bold.ttf');
font-style: normal;
font-weight: normal;
}
/* animations */
@ -21,8 +31,9 @@ body{
position: relative;
min-width: 900px;
margin:20px;
font-family: unifont, sans-serif;
font-family: mono, sans-serif;
font-size: 8px;
background-color: #f0dfff;
overflow-x: hidden;
z-index: -1;
}
@ -51,12 +62,18 @@ p{
margin:0;
}
code{
font-family: 'unifont';
font-family: 'mono';
font-size: 16px;
}
blockquote{
margin-left:50px;
}
i{
vertical-align: text-bottom;
position: absolute;
margin-left: 3.5em;
margin-top: -1px;
}
.blink{
animation: 2s linear 1s infinite blink;
}
@ -66,11 +83,11 @@ blockquote{
z-index: -1;
width: calc(100% - 400px);
min-width: 600px;
/*width: calc(100% - 300px);*/
margin:10px 0 20px 0;
font-family: unifont, sans-serif;
font-family: mono, sans-serif;
font-size: 16px;
line-height: 1.35;
line-height: 1.65;
letter-spacing: -0.01em;
}
#nav-wrapper{
position: relative;
@ -85,7 +102,8 @@ blockquote{
#logo a{
font-family: 'script';
font-size: 64px;
font-weight: bold;
/*font-weight: bold;*/
-webkit-text-stroke: 2px black;
line-height: 1;
letter-spacing: -0.035em;
border: 0;
@ -101,17 +119,19 @@ blockquote{
width: 100%;
height: 40px;
padding:0px 10px;
border:1px solid black;
border:1px dotted;
font-family: 'mono';
font-size: 16px;
background-color: #f2f2f3;
}
#search #submit{
position: absolute;
width: 26px;
height: 26px;
right: -12px;
top:24px;
border:0;
border-radius: 100%;
background-color:transparent;
width: 103px;
height: 42px;
right: -140px;
top: 15px;
font-family: 'mono';
font-size: 16px;
text-align: center;
}
#search #submit:hover{
@ -142,16 +162,25 @@ blockquote{
strong, strong.query, strong.word, .result{
font-family: 'script';
font-size: 22px;
line-height: 1.35;
font-weight: bold;
letter-spacing: -0.035em;
line-height: 1.5;
/*font-weight: bold;*/
-webkit-text-stroke: 1px;
letter-spacing: 0.015em;
}
.guides{
max-width: 600px;
margin:2em 0 4em 10px;
}
.guides li{
margin-bottom: 0.5em;
}
/* crossing TEXT */
.cross{
position: relative;
max-width: 800px;
margin-top: 1em;
max-width: 1000px;
margin-top: 4em;
padding-right: 2em;
clear: both;
}
@ -174,6 +203,7 @@ strong, strong.query, strong.word, .result{
p.techfem:before{
content:' ◕';
padding-right: 0.5em;
vertical-align: text-bottom;
}
p.tfidf{
}
@ -185,12 +215,16 @@ strong, strong.query, strong.word, .result{
p.tfidf:before{
content:'◧';
padding-right: 0.5em;
vertical-align: text-bottom;
}
p.note{
width: 100%;
text-align: center;
padding-bottom: 1em;
}
.cross strong{
line-height: 0;
}
/* make sure that these blocks don't flow into the cross text blocks*/
#results, #notused, #suggestions, #conditionals, #analytics ,.analytics, .mappings, #colophon{
@ -220,9 +254,10 @@ strong, strong.query, strong.word, .result{
text-align: center;
}
.result .title, .result .ascii{
font-family: 'unifont';
font-family: 'mono';
font-size: 16px;
font-weight: normal;
-webkit-text-stroke: 0;
}
.result .title{
padding:10px;
@ -236,7 +271,7 @@ strong, strong.query, strong.word, .result{
top:-7px;
margin:20px;
font-size: 16px;
line-height: 1.2;
line-height: 1.4;
}
#txt-list ul{
margin:1em 0 0 0;
@ -244,10 +279,9 @@ strong, strong.query, strong.word, .result{
}
#txt-list ul li{
margin:0;
padding:0 0 10px 0;
text-indent: -40px;
padding:0 0 1em 0;
text-indent: -3.2em;
list-style: none;
/*word-break: break-all;*/
}
#txt-list li a.contrast, a.contrast{
border: 0;
@ -256,7 +290,7 @@ strong, strong.query, strong.word, .result{
#colophon{
display: block;
width: 100%;
margin-left: 2em;
margin: 5em 0;
}
#manifesto_content_wrapper{
@ -273,6 +307,8 @@ strong, strong.query, strong.word, .result{
}
iframe#manifesto_content {
width: 100%;
height: calc(100vh - 200px);
height: calc(100vh - 300px);
border:1px dotted;
background-color: white;
}

BIN
static/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

38
templates/en/colophon.html → templates/en/about.html

@ -8,17 +8,40 @@
<br>
<br>
<br>
<br>
<br>
<div id ="colophon">
<div id="intro" class="cross">
<p>A cross-reading allows for a specific type of reading that does not follow a linear order, but follows a self-chosen path. Reading becomes an act of creating relations and threading connections, reading across different domains. </p>
<p>This cyber/technofeminist cross-reader does not follow one but two axes, bridging the act of reading a collection of texts, with the act of reading a tool. Reading across a collection of manifestos, while reading the algorithm that is used to do so.</p>
<p>These cross-readings connect ...</p>
<p class="tfidf">... the <em>Term Frequency Inverse Document Frequency</em> algorithm, or <em>TF-IDF</em> in short</p>
<p class="techfem">... a collection of <em>cyber- and technofeminist manifestos</em></p>
<p class="tfidf">The TF-IDF is a commonly used algorithm to find the most important words of a document. The algorithm is (partly) written by the female computer scientist Karen Spärck Jones in the 1970s and has become one of the important algorithms of many search tools online, such as digital library systems or corporate search engines like Yandex or Google. The algorithm turns written documents into a sorted lists of search results, using a specific relative and inversed way of counting, that is sensitive for contrast in written documents. </p>
<p class="techfem">The cyber/technofeminist manifestos connect feminist thinking to technology, introducing feminist servers, cyborg figures, cyberwitches, or pleas for the glitch as cultural digital artefact. This collection, which is obviously incomplete, brings a diverse set of technofeminist documents together that are published between 1912 and 2019. The manifestos speak about very different concerns and questions, but they connect in terms of energy level. Urging to make a statement, ready to activate.
<br><br>
An interesting note to mention: Karen Spärck Jones was an advocate for the position of women in computing. <em>“I’ve been trying to think a little bit—but it’s very dispiriting!—about how to try to get more women into computer science. On the whole, everybody who thinks about this is depressed, because we’re going backwards rather than forwards.”</em> <sup><a href="https://ethw.org/Oral-History:Karen_Sp%C3%A4rck_Jones#On_Getting_More_Women_into_Computer_Science"></a></sup></p>
<p>These two axes, the algorithm and the manifestos, interoperate. They support and strengthen eachother as the X and Y of this cross-reading tool. </p>
<p>The TF-IDF algorithm, while responding to a search request, creates cross-readings through the manifestos. It outputs a list of search results around the subject of search, creating a field of statements, questions and concerns around one single word. Meanwhile, the algorithm starts to interoperate with the manifesto as a format. Sensitive as it is for bulletpointed writing, repetition and unique words -- elements that are used a lot in these statement driven documents. The algorithm prioritizes higher contrastful language over academic writing, repetition over very diverse vocabularies and the use of unique words over the use of common ones.</p>
<p>See this cross-reading tool as an exercise in reading, across a field of technofeminist thinking and a tool for algorithmic sorting.</p>
<!-- <p>Reading the TF-IDF algorithm by itself only results in a technical understanding of this old artefact.</p> -->
<!-- <p>This algorithm thereby connects a discrete procedure (that of computing) to a very vivid and strong document format: the manifesto.</p> -->
</div>
<div id="colophon">
<h1>Colophon</h1>
<p>
The <em>cyber/technofeminist cross-reader</em> is developed by <a href="http://manettaberends.nl/">Manetta Berends</a><br />
in the context of the exhibition <em>Computer Grrrls</em> in Paris (March - July 2019).<br>
</p>
<br>
<br>
<p>
Commissioned by:<br />
Inke Arns (Hartware Medien Kunst Verein, Dortmund)<br />
@ -33,7 +56,7 @@
Julie Boschat-Thorez</p>
<p><br />
Fonts:<br />
Unifont<br />
Go-Mono<br />
Liberation Sans Narrow Bold<br />
<br />
Software:<br />
@ -52,9 +75,7 @@
This project is made possible with the support of the DICRéAM fund, Paris.
</p>
</div>
<br>
<div class="cross">
<br>
<p class="note">[Note on context]</p>
<p class="techfem">
The collection of cyber/technofeminist manifestos includes the following documents:
@ -130,7 +151,6 @@
<em>Cyberwitches Manifesto </em>[EN, FR] <br>
written by Lucile Haute (2019)<br>
<br>
<br>
</p>
<p class="tfidf">The algorithm introduces the idea of a <em>context specific way</em> of counting words.
<br />

6
templates/en/base.html

@ -13,7 +13,7 @@
{% for filename in filenames | sort %}
<li>
<a href="/{{ lang }}/manifesto/{{ filename | replace('.txt','') }}">{{ filename | prettyfilename }}</a>
<a class="contrast" href="/{{ lang }}/mappings/{{ filename | replace('.txt','') }}"></a>
<a class="contrast" href="/{{ lang }}/mappings/{{ filename | replace('.txt','') }}"><i></i></a>
</li>
{% endfor %}
<ul>
@ -25,7 +25,7 @@
<div id="colophon_button">
EN / <a href="/fr">FR</a>
&nbsp;
<a href="/{{ lang }}/colophon">colophon</a>
<a href="/{{ lang }}/about">about</a>
</div>
<div id="logo">
<a href="/{{ lang }}/">cyber/technofeminist <br>cross-readings</a>
@ -34,7 +34,7 @@
<div id="search">
<form action="" method="GET">
<input id="query" name="q" value="{{query}}"/>
<input id="submit" type="submit" value=""/>
<input id="submit" type="submit" value="search"/>
</form>
</div>
{% endblock %}

49
templates/en/index.html

@ -1,37 +1,28 @@
{% extends "en/base.html" %}
{% block results %}
<div id="intro" class="cross">
<blockquote>
Exchanges between a collection of <em>cyber/technofeminist manifestos</em><br>
and the <em>Term Frequency - Inversed Document Frequency algorithm (TF-IDF)</em>.
</blockquote>
<!-- <p>Psst, this is a cross-reading tool that operates on two axes ...</p> -->
<!-- <p>Tip: Try to search for a single word.</p> -->
<p>A cross-reading allows for a specific type of reading that does not follow a linear order, but follows a self-chosen path. Reading becomes an act of creating relations and threading connections, reading across different domains. </p>
<p>This cyber/technofeminist cross-reader does not follow one but two axes, bridging the act of reading a collection of texts, with the act of reading a tool. Reading across a collection of manifestos, while reading the algorithm that is used to do so.</p>
<p>These cross-readings connect ...</p>
<p class="tfidf">... the <em>Term Frequency Inverse Document Frequency</em> algorithm, or <em>TF-IDF</em> in short</p>
<p class="techfem">... a collection of <em>cyber- and technofeminist manifestos</em></p>
<p class="tfidf">The TF-IDF is a commonly used algorithm to find the most important words of a document. The algorithm is (partly) written by the female computer scientist Karen Spärck Jones in the 1970s and has become one of the important algorithms of many search tools online, such as digital library systems or corporate search engines like Yandex or Google. The algorithm turns written documents into a sorted lists of search results, using a specific relative and inversed way of counting, that is sensitive for contrast in written documents. </p>
<p class="techfem">The cyber/technofeminist manifestos connect feminist thinking to technology, introducing feminist servers, cyborg figures, cyberwitches, or pleas for the glitch as cultural digital artefact. This collection, which is obviously incomplete, brings a diverse set of technofeminist documents together that are published between 1912 and 2019. The manifestos speak about very different concerns and questions, but they connect in terms of energy level. Urging to make a statement, ready to activate.
<br><br>
An interesting note to mention: Karen Spärck Jones was an advocate for the position of women in computing. <em>“I’ve been trying to think a little bit—but it’s very dispiriting!—about how to try to get more women into computer science. On the whole, everybody who thinks about this is depressed, because we’re going backwards rather than forwards.”</em> <sup><a href="https://ethw.org/Oral-History:Karen_Sp%C3%A4rck_Jones#On_Getting_More_Women_into_Computer_Science"></a></sup></p>
<p>These two axes, the algorithm and the manifestos, interoperate. They support and strengthen eachother as the X and Y of this cross-reading tool. </p>
<p>The TF-IDF algorithm, while responding to a search request, creates cross-readings through the manifestos. It outputs a list of search results around the subject of search, creating a field of statements, questions and concerns around one single word. Meanwhile, the algorithm starts to interoperate with the manifesto as a format. Sensitive as it is for bulletpointed writing, repetition and unique words -- elements that are used a lot in these statement driven documents. The algorithm prioritizes higher contrastful language over academic writing, repetition over very diverse vocabularies and the use of unique words over the use of common ones.</p>
<p>See this cross-reading tool as an exercise in reading, across a field of technofeminist thinking and a tool for algorithmic sorting.</p>
<!-- <p>Reading the TF-IDF algorithm by itself only results in a technical understanding of this old artefact.</p> -->
<!-- <p>This algorithm thereby connects a discrete procedure (that of computing) to a very vivid and strong document format: the manifesto.</p> -->
</div>
<div class="guides">
<ol>
<li>
You can search for a word and see if it creates any cross-readings in the collection.
</li>
<li>
You can browse through the collection of manifestos and read them in their own web environnments.
</li>
<li>
If you click on the little ◐ icon next to the title of the manifesto, you can read the manifesto through the TF-IDF algorithm.
</li>
</ol>
</div>
{% endblock %}
{% block suggestions %}
<br>
<h1>Cross-reading suggestions (selected):</h1>
<div>
{% for word in suggestions %}
@ -39,10 +30,10 @@
{% endfor %}
</div>
<br>
<h1>Contrast-mapping suggestions (top 100 TF-IDF results):</h1>
<h1>Cross-reading suggestions (top 100 TF-IDF results):</h1>
<div>
{% for tfidf, word in mappings %}
<strong class="query" style="font-size:{{ 50 + tfidf / 5 }}%;"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% for word in mappings %}
<strong class="query"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% endfor %}
</div>
<br>

3
templates/en/manifesto.html

@ -11,10 +11,13 @@
<div id="manifesto_content_wrapper">
{% if '.jpg' in link %}
<img src="{{ link }}" />
<br>
{% elif 'vimeo' in link %}
<iframe src="{{ link }}" width="600" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
{% else %}
<iframe id="manifesto_content" src="{{ link }}"></iframe>
{% endif%}
<br>
<div>{{ link }}</div>
</div>
{% endblock %}

11
templates/en/mappings-name.html

@ -6,8 +6,9 @@
{% block results %}
<div class="cross">
<p class="tfidf" style="margin-left: calc(50% + 1.5em);">
<br><br>
<p class="note">[Note on contrast mappings]</p>
<p class="tfidf" style="float: right;margin-left:1em;">
<code>
def tfidf(query, words, corpus):<br /><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Term Frequency<br />
@ -27,11 +28,7 @@
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return tf_count, tf_count, tfidf_value
</code>
</p>
<br><br>
<p class="note">[Note on contrast mappings]</p>
<p class="tfidf" style="float: right;margin-left:1em;">
<br><br>
The TF-IDF algorithm, shown above in the programming language Python, weaves a layer of contrast into the text. Not literally, but in the form of numbers. The most contrastful words are those that the algorithm consideres as the most important words for that text.
<br><br>
These contrast mappings allow for reading across the manifesto and the algorithm.

52
templates/en/results.html

@ -33,41 +33,12 @@
{% endfor %}
</div>
</div>
<br>
<br>
<br>
<div class="cross">
<p class="note">[Note on activating]</p>
<p class="tfidf">
The <em>TF-IDF algorithm</em> is an activator. Activating non-linear threads through a dataset of words.
<br><br>
As a navigator the algorithm is a provider of order, deciding on the importance of the search term for a manifesto.
</p>
<p class="techfem">
The <em>cyber- and technofeminist manifesto</em> are written and published to activate. Declaring intentions, motives or specific views on technology. Their writing styles, different as they are, are often statement-based, short and sometimes militant.
<br><br>
<em>&quot;Nothing should be accepted as fixed, permanent, or 'given' -- neither material conditions nor social forms..&quot;</em> (Xenofeminist manifesto), <br>
<em>&quot;So that is why no revolution should be without her.&quot;</em> (The Manifesto of Futurist Woman)
</p>
</div>
{% endif %}
<br>
<br>
<br>
<br>
<br>
<br>
<br>
{% endblock %}
{% block suggestions %}
<div id="suggestions">
<h1>SUGGESTIONS</h1>
<p class="cross">The cross-reader took the freedom to suggest. Some of its suggestions are pre-selected, such as the list of suggested cross-readings. Other suggestions are generated, using language as a playful tool to trigger connections and explore the dimensionality of a single word.</p>
<br>
{% if analytics %}
{% if analytics.stemmer %}
@ -91,21 +62,34 @@
<br>
<div class="suggestions tfidf">
<h1>Contrast mappings suggestions (top 50 TF-IDF results) for <em>{{ results[0]['name']}}</em>: <br></h1>
<h1>Cross-reading suggestions (top 50 TF-IDF results) through <em>{{ results[0]['name']}}</em>: <br></h1>
<div class="">
{% for tfidf, word in analytics.mappings[:50] %}
{% if word == query %}
<strong class="word" style="font-size:{{ 100 + tfidf }}%;">{{ word }}</strong>
<strong class="word">{{ word }}</strong>
{% else %}
<strong class="word" style="font-size:{{ 100 + tfidf }}%;"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endif%}
{% endfor%}
</div>
<br>
<div><a class="contrast" href="/{{ lang}}/mappings/{{ results[0]['filename'].strip() | replace('.txt','') }}">Read more ◐</a></div>
<br>
<br>
</div>
{% endif%}
</div>
<div class="cross">
<p class="note">[Note on activating]</p>
<p class="tfidf">
The <em>TF-IDF algorithm</em> is an activator. Activating non-linear threads through a dataset of words.
<br><br>
As a navigator the algorithm is a provider of order, deciding on the importance of the search term for a manifesto.
</p>
<p class="techfem">
The <em>cyber- and technofeminist manifesto</em> are written and published to activate. Declaring intentions, motives or specific views on technology. Their writing styles, different as they are, are often statement-based, short and sometimes militant.
<br><br>
<em>&quot;Nothing should be accepted as fixed, permanent, or 'given' -- neither material conditions nor social forms..&quot;</em> (Xenofeminist manifesto), <br>
<em>&quot;So that is why no revolution should be without her.&quot;</em> (The Manifesto of Futurist Woman)
</p>
</div>
{% endblock %}

38
templates/fr/colophon.html → templates/fr/about.html

@ -9,19 +9,37 @@
<br>
<br>
<br>
<br>
<br>
<div id="intro" class="cross">
<p>La lecture transversale permet un type de lecture spécifique, ne poursuivant pas un ordre linéaire, selon un parcours choisi. La lecture devient un acte de création de relations et de tissage de connections, via la traversée de différents domaines.</p>
<p>Cette liseuse transversale cyber/technoféministe s’établit sur deux axes, alliant la lecture d’un corpus de textes et celle d’un outil technologique. Le processus de lecture englobe un ensemble de manifestes ainsi que l’algorithme utilisé pour ce faire.</p>
<p>Ces lectures transversales connectent ...</p>
<p class="tfidf">... l’algorithme TF-IDF, de l’anglais <em>Term Frequency Inverse Document Frequency</em></p>
<p class="techfem">... et une <em>collection de manifestes cyber et technoféministes</em></p>
<p class="tfidf">Le TF-IDF est un algorithme utilisé communément afin d’identifier les mots les plus importants au sein d’un document. Cet algorithme a été en partie développé par l’informaticienne Späcrk Jones dans les années 70. Il est devenu l’un des algorithmes les plus importants pour un grand nombre de moteurs de recherche en ligne tels que Yandex ou Google. L’algorithme transforme les documents textuels en listes, où les résultats de recherche sont triés. Il utilise un mode de comptage inversé, sensible aux variations présentes au sein de ces documents.</p>
<p class="techfem">Les manifestes cyber/technoféministes lient pensée féministe et technologie, en introduisant le concept de serveurs féministes, des figures cyborg, des cyber-sorcières, voire des plaidoyers à la faveur du glitch comme artefact culturel numérique. Cette collection, évidemment non exhaustive, rassemble divers documents technoféministes publiés entre 1912 et 2019. Bien que ces manifestes évoquent des questions et préoccupations diverses, ils convergent sur le plan de l’énergie déployée. Ils posent l’urgence d’établir un constat, prêts à être mis en oeuvre.
<br><br>
Par ailleurs, il convient de noter que Karen Spärck Jones défendait la place des femmes dans le milieu informatique. <em>“J’ai essayé de réfléchir un peu – mais c’est très décourageant! - à la façon de parvenir à ce que plus de femmes soient présentes en informatique. Globalement, chaque personne réfléchissant sur le sujet finit par être déprimée, car nous reculons plus que nous ne progressons.”</em> <sup><a href="https://ethw.org/Oral-History:Karen_Sp%C3%A4rck_Jones#On_Getting_More_Women_into_Computer_Science"></a></sup></p>
<p>Ces deux axes, celui de l’algorithme et celui des manifestes, opèrent ensemble. Ils se soutiennent et se renforcent mutuellement, créant de nouvelles dimensions de lectures via cette liseuse transversale.</p>
<p>L’algorithme TF-IDF génère une lecture transversale des manifestes tout en répondant à une requête. Il en ressort une liste de résultats autour du terme; un ensemble de déclarations, questions et préoccupations autour d’un même terme. Simultanément, l’algorithme interagit avec le format du manifeste : il est sensible aux puces typographiques, aux répétitions et aux mots uniques – des éléments qui caractérisent ces documents d’ordre déclaratif. L’algorithme donne la priorité aux formes textuelles très contrastées par rapport à celles ayant un style plus académique, à la répétition sur la diversité de vocabulaire, et à l’usage de mots uniques sur les mots plus communs.</p>
<p>Cet outil de lecture transversale est donc à considérer tel un exercice de lecture, à travers le champ commun de la pensée technoféministe et d’un outil de classification algorithmique.</p>
</div>
<div id ="colophon">
<h1>Colophon</h1>
<p>
La <em>cyber/technofeminist cross-reader</em> a été développée par <a href="http://manettaberends.nl/">Manetta Berends</a><br>
pour l’exposition <em>Computer Grrrls</em> à Paris (Mars - Juillet 2019).<br>
</p>
<br>
<br>
<p>
Commission par:<br />
Inke Arns (Hartware Medien Kunst Verein, Dortmund)<br>
@ -35,7 +53,7 @@
Julie Boschat-Thorez<br>
<br />
Polices d’écriture:<br />
Unifont<br />
Go-Mono<br />
Liberation Sans Narrow Bold<br />
<br />
Logiciel:<br />
@ -55,13 +73,8 @@
</p>
</div>
<br>
<div class="cross">
<br>
<p class="note">[Note sur la contextualisation]</p>
<p class="techfem">
La collection des manifestes cyber/technoféministes comprend les documents suivants:
<br><br>
@ -137,7 +150,6 @@
<em>Cyberwitches Manifesto </em>[EN, FR] <br>
par Lucile Haute (2019)<br>
<br>
<br>
</p>
<p class="tfidf">L’algorithme amorce des idées sur le comptage localisé de mots.
<br />

8
templates/fr/base.html

@ -8,12 +8,12 @@
</head>
<body>
<div id="txt-list">
<p><em>Processing</em> and <em>cross-calculating</em> through the following manifesto's:</p>
<p><em>Traitement</em> et <em>calcul croisé</em> à travers les manifestes suivants:</p>
<ul>
{% for filename in filenames | sort %}
<li>
<a href="/{{ lang }}/manifesto/{{ filename | replace('.txt','') }}">{{ filename | prettyfilename }}</a>
<a class="contrast" href="/{{ lang }}/mappings/{{ filename | replace('.txt','') }}"></a>
<a class="contrast" href="/{{ lang }}/mappings/{{ filename | replace('.txt','') }}"><i></i></a>
</li>
{% endfor %}
<ul>
@ -25,7 +25,7 @@
<div id="colophon_button">
<a href="/en">EN</a> / FR
&nbsp;
<a href="/{{ lang }}/colophon">colophon</a>
<a href="/{{ lang }}/about">le projet</a>
</div>
<div id="logo">
<a href="/{{ lang }}/">cyber/technofeminist <br>cross-readings</a>
@ -34,7 +34,7 @@
<div id="search">
<form action="" method="GET">
<input id="query" name="q" value="{{query}}"/>
<input id="submit" type="submit" value=""/>
<input id="submit" type="submit" value="search"/>
</form>
</div>
{% endblock %}

47
templates/fr/index.html

@ -1,38 +1,25 @@
{% extends "fr/base.html" %}
{% block results %}
<div id="intro" class="cross">
<blockquote>Échanges entre une <em>collection de manifestes cyber/technoféministes</em>
<br>et <em>l’algorithme “Term Frequency – Inversed Document Frequency” (TF-IDF)</em>.</blockquote>
<br>
<br>
<p>La lecture transversale permet un type de lecture spécifique, ne poursuivant pas un ordre linéaire, selon un parcours choisi. La lecture devient un acte de création de relations et de tissage de connections, via la traversée de différents domaines.</p>
<p>Cette liseuse transversale cyber/technoféministe s’établit sur deux axes, alliant la lecture d’un corpus de textes et celle d’un outil technologique. Le processus de lecture englobe un ensemble de manifestes ainsi que l’algorithme utilisé pour ce faire.</p>
<p>Ces lectures transversales connectent ...</p>
<p class="tfidf">... l’algorithme TF-IDF, de l’anglais <em>Term Frequency Inverse Document Frequency</em></p>
<p class="techfem">... et une <em>collection de manifestes cyber et technoféministes</em></p>
<p class="tfidf">Le TF-IDF est un algorithme utilisé communément afin d’identifier les mots les plus importants au sein d’un document. Cet algorithme a été en partie développé par l’informaticienne Späcrk Jones dans les années 70. Il est devenu l’un des algorithmes les plus importants pour un grand nombre de moteurs de recherche en ligne tels que Yandex ou Google. L’algorithme transforme les documents textuels en listes, où les résultats de recherche sont triés. Il utilise un mode de comptage inversé, sensible aux variations présentes au sein de ces documents.</p>
<p class="techfem">Les manifestes cyber/technoféministes lient pensée féministe et technologie, en introduisant le concept de serveurs féministes, des figures cyborg, des cyber-sorcières, voire des plaidoyers à la faveur du glitch comme artefact culturel numérique. Cette collection, évidemment non exhaustive, rassemble divers documents technoféministes publiés entre 1912 et 2019. Bien que ces manifestes évoquent des questions et préoccupations diverses, ils convergent sur le plan de l’énergie déployée. Ils posent l’urgence d’établir un constat, prêts à être mis en oeuvre.
<br><br>
Par ailleurs, il convient de noter que Karen Spärck Jones défendait la place des femmes dans le milieu informatique. <em>“J’ai essayé de réfléchir un peu – mais c’est très décourageant! - à la façon de parvenir à ce que plus de femmes soient présentes en informatique. Globalement, chaque personne réfléchissant sur le sujet finit par être déprimée, car nous reculons plus que nous ne progressons.”</em> <sup><a href="https://ethw.org/Oral-History:Karen_Sp%C3%A4rck_Jones#On_Getting_More_Women_into_Computer_Science"></a></sup></p>
<p>Ces deux axes, celui de l’algorithme et celui des manifestes, opèrent ensemble. Ils se soutiennent et se renforcent mutuellement, créant de nouvelles dimensions de lectures via cette liseuse transversale.</p>
<p>L’algorithme TF-IDF génère une lecture transversale des manifestes tout en répondant à une requête. Il en ressort une liste de résultats autour du terme; un ensemble de déclarations, questions et préoccupations autour d’un même terme. Simultanément, l’algorithme interagit avec le format du manifeste : il est sensible aux puces typographiques, aux répétitions et aux mots uniques – des éléments qui caractérisent ces documents d’ordre déclaratif. L’algorithme donne la priorité aux formes textuelles très contrastées par rapport à celles ayant un style plus académique, à la répétition sur la diversité de vocabulaire, et à l’usage de mots uniques sur les mots plus communs.</p>
<p>Cet outil de lecture transversale est donc à considérer tel un exercice de lecture, à travers le champ commun de la pensée technoféministe et d’un outil de classification algorithmique.</p>
</div>
<br>et <em>l’algorithme “Term Frequency – Inversed Document Frequency” (TF-IDF)</em>.</blockquote>
<div class="guides">
<ol>
<li>
Vous pouvez rechercher un mot et voir s'il crée des lectures croisées dans la collection.
</li>
<li>
Vous pouvez parcourir la collection de manifestes et les lire dans leur propre environnement web.
</li>
<li>
Si vous cliquez sur la petite icône ◐ à côté du titre du manifeste, vous pouvez lire le manifeste via l'algorithme TF-IDF.
</li>
</ol>
</div>
{% endblock %}
{% block suggestions %}
<br>
<h1>Suggestions de lectures croisées:</h1>
<div>
{% for word in suggestions %}
@ -42,8 +29,8 @@
<br>
<h1>Suggestions du mapping de contraste (top 100 TF-IDF résultats):</h1>
<div>
{% for tfidf, word in mappings %}
<strong class="query" style="font-size:{{ 50 + tfidf / 5 }}%;"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% for word in mappings %}
<strong class="query"> <a href="/{{ lang }}/?q={{ word }}">{{ word }}</a> </strong>
{% endfor %}
</div>
<br>

11
templates/fr/manifesto.html

@ -11,10 +11,21 @@
<div id="manifesto_content_wrapper">
{% if '.jpg' in link %}
<img src="{{ link }}" />
<br>
{% elif 'vimeo' in link %}
<iframe src="{{ link }}" width="600" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<div><em>
every day, you willingly exchange personal data for custom convenience <br>
lurking behind these transactions, the corporatocracy maps out your every move in the name of security <br>
don't worry, we're on your side <br>
the hors will help you reclaim your life and reprogram the 1s and 0s that build our world <br>
to hack is to create <br>
what we do is self defense, self determin- [end of transmission] <br>
</em></div>
{% else %}
<iframe id="manifesto_content" src="{{ link }}"></iframe>
{% endif%}
<br>
<div>{{ link }}</div>
</div>
{% endblock %}

10
templates/fr/mappings-name.html

@ -6,8 +6,8 @@
{% block results %}
<div class="cross">
<p class="tfidf" style="margin-left: calc(50% + 1.5em);">
<p class="note">[Note sur les mappings de contraste]</p>
<p class="tfidf" style="float: right;margin-left:1em;">
<code>
def tfidf(query, words, corpus):<br /><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Term Frequency<br />
@ -27,11 +27,7 @@
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return tf_count, tf_count, tfidf_value
</code>
</p>
<br><br>
<p class="note">[Note sur les mappings de contraste]</p>
<p class="tfidf" style="float: right;margin-left:1em;">
<br><br>
L’algorithme TF-IDF, formaté ci dessus dans le language de programmation Python, intègre un niveau de contraste au sein du texte, sous une forme numérique. Les mots se démarquant le plus fortement sont considérés par l’algorithme comme les plus importants pour ce texte.
<br><br>
Ces mappings de contraste permettent une lecture simultannée des manifestes et de l’algorithme.

50
templates/fr/results.html

@ -36,36 +36,11 @@
{% endfor %}
</div>
</div>
<br><br><br>
<div class="cross">
<p class="note">[Note on activating]</p>
<p class="tfidf">
L’algorithme <em>TF-IDF</em> est un catalyseur, générant des connections multidimentionelles à travers un ensemble de mots, qui constituent ici les données.
<br><br>
Tel un guide pour le lecteur, l’algorithme délivre un classement, en décidant de l’importance du terme de recherche au sein de chaque manifeste.
</p>
<p class="techfem">
Les <em>manifestes cyber et technoféministes</em> sont écrits et publiés dans un but d’application. Ils émettent des déclarations sur les intentions, motivations et vues spécifiques sur la technologie. Leurs styles d’écriture, aussi différents soient-ils, sont souvent basés sur la mise en forme de déclarations courtes, voire même militantes.
<br><br>
<em>«Rien ne devrait être admis comme figé, permanent ou «donné» – ni les conditions matérielles ni les formes sociales»</em> (Manifeste Xénoféministe), <br>
<em>«Voilà pourquoi aucune révolution ne doit lui rester étrangère.»</em> (Le manifeste de la femme futuriste)
</p>
</div>
{% endif %}
<br>
<br>
<br>
<br>
<br>
{% if analytics %}
<div id="analytics">
<h1>SUGGESTIONS</h1>
<p>La liseuse transversale est dotée d’une liberté de suggestion. Certaines de ses suggestions sont pré sélectionnées, notamment avec la liste de lectures croisées proposées. D’autres suggestions sont automatiquement générées, l’algorithme étant utilisé comme un outil ludique afin d’initier des connections et d’explorer la dimensionnalité d’un mot unique.</p>
<br>
{% if analytics.stemmer %}
<div id="similars" class="analytics stemmer">
<h2>Similaire mais différent de <em>{{ query }}</em>:</h2>
@ -73,6 +48,7 @@
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endfor%}
</div>
<br>
{% endif%}
</div> <!-- #analytics -->
{% endif%}
@ -90,24 +66,38 @@
{% if analytics.mappings %}
<br>
<div class="suggestions tfidf">
<h1>Suggestions du mapping de contraste (top 50 TF-IDF résultats) à <em>{{ results[0]['name']}}</em>: <br></h1>
<h1>Suggestions de lectures croisées (top 50 TF-IDF résultats) à <em>{{ results[0]['name']}}</em>: <br></h1>
<div class="">
{% for tfidf, word in analytics.mappings[:50] %}
{% if word == query %}
<strong class="word" style="font-size:{{ 100 + tfidf }}%;">{{ word }}</strong>
<strong class="word">{{ word }}</strong>
{% else %}
<strong class="word" style="font-size:{{ 100 + tfidf }}%;"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
<strong class="word"><a href="/{{ lang}}/?q={{ word }}">{{ word }}</a></strong>
{% endif%}
{% endfor%}
</div>
<br>
<div><a class="contrast" href="/{{ lang}}/mappings/{{ results[0]['filename'].strip() | replace('.txt','') }}">Pour approfondir l’exploration du mapping de contraste appliqué au texte entier (<em>{{ results[0]['name'].strip() }}</em>) par ici ◐.</a></div>
<br>
<br>
<div><a class="contrast" href="/{{ lang}}/mappings/{{ results[0]['filename'].strip() | replace('.txt','') }}">Pour approfondir l’exploration du mapping <br>de contraste appliqué au texte entier <br>(<em>{{ results[0]['name'].strip() }}</em>) par ici ◐.</a></div>
</div>
{% endif%}
</div>
<div class="cross">
<p class="note">[Note on activating]</p>
<p class="tfidf">
L’algorithme <em>TF-IDF</em> est un catalyseur, générant des connections multidimentionelles à travers un ensemble de mots, qui constituent ici les données.
<br><br>
Tel un guide pour le lecteur, l’algorithme délivre un classement, en décidant de l’importance du terme de recherche au sein de chaque manifeste.
</p>
<p class="techfem">
Les <em>manifestes cyber et technoféministes</em> sont écrits et publiés dans un but d’application. Ils émettent des déclarations sur les intentions, motivations et vues spécifiques sur la technologie. Leurs styles d’écriture, aussi différents soient-ils, sont souvent basés sur la mise en forme de déclarations courtes, voire même militantes.
<br><br>
<em>«Rien ne devrait être admis comme figé, permanent ou «donné» – ni les conditions matérielles ni les formes sociales»</em> (Manifeste Xénoféministe), <br>
<em>«Voilà pourquoi aucune révolution ne doit lui rester étrangère.»</em> (Le manifeste de la femme futuriste)
</p>
</div>
<!--
<h1>Request conditional fragments:</h1>
<div id="suggestions">

27
templates/fr/results_lists.html

@ -1,27 +0,0 @@
{% extends "fr/base.html" %}
{% block title %}{{query}}{% endblock %}
{% block txtlist %}
<div id="more-descr">[<span class="asterix">*</span>] The algorithm is asked to not return more than 3 sentences from the same manifesto. There are more sentences that match this search query!</div>
{% endblock %}
{% block results %}
<h1>The results for the query "{{query}}" are:</h1>
<div id="results" class="lists">
{% if results == {} %}
<div>That word is not used in any of the manifesto's.</div>
{% else %}
{% for _, manifesto in results.items() %}
<span class="result">
<h2 class="title">{{manifesto.name}}</h2>
<span class="list">
{% for i in range(manifesto.tf) %}
<strong style="font-size:{{manifesto.tfidf * 10000}}px;">{{query}}</strong>
{% endfor %}
</span>
</span>
{% endfor %}
<hr>
{% endif %}
</div>
{% endblock %}

50
tfidf.top50.txt

@ -0,0 +1,50 @@
cyberfeminism
TO
ist
IT
REFUGIA
cunt
BECAUSE
cyberfeminismus
AND
THE
WE
IS
OF
WORK
Data
THAT
VNS
nicht
FACEBOOK
WAGES
nije
OUR
your
xyz
worry
willingly
wearehors
transmission
transactions
reprogram
lurking
hors
determin
custom
corporatocracy
convenience
Hackers
1s
0s
data
internet
glitch
con
YOU
FROM
keine
Mundane
FOR
nodes
Matrix
Loading…
Cancel
Save