From be651b698fe6660702288640ffdd2f104e6d7acc Mon Sep 17 00:00:00 2001
From: Fabian Gallenkamp <fabian.gallenkamp@uni-hamburg.de>
Date: Wed, 27 Feb 2019 17:09:42 +0100
Subject: [PATCH] Various

---
 README.md                           |   2 +
 README.rst                          |  27 --
 app.py                              | 431 +++++++++++++++++++++++-----
 sample_db.sqlite                    | Bin 69632 -> 81920 bytes
 templates/export/MethodsList.jinja2 |  10 +
 5 files changed, 378 insertions(+), 92 deletions(-)
 delete mode 100644 README.rst
 create mode 100644 templates/export/MethodsList.jinja2

diff --git a/README.md b/README.md
index e69de29..fc4e9a8 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,2 @@
+# digital methods
+Please visit the [Wiki](../../wiki)!
\ No newline at end of file
diff --git a/README.rst b/README.rst
deleted file mode 100644
index d06c87d..0000000
--- a/README.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-SQLAlchemy model backend integration examples.
-
-To run this example:
-
-1. Clone the repository::
-
-    git clone https://github.com/flask-admin/flask-admin.git
-    cd flask-admin
-
-2. Create and activate a virtual environment::
-
-    virtualenv env
-    source env/bin/activate
-
-3. Install requirements::
-
-    pip install -r 'examples/sqla/requirements.txt'
-
-4. Run the application::
-
-    python examples/sqla/app.py
-
-The first time you run this example, a sample sqlite database gets populated automatically. To suppress this behaviour,
-comment the following lines in app.py:::
-
-    if not os.path.exists(database_path):
-        build_sample_db()
diff --git a/app.py b/app.py
index 2936940..9b7e7d2 100644
--- a/app.py
+++ b/app.py
@@ -7,10 +7,14 @@ from flask import Flask, flash, send_file, url_for
 from flask_sqlalchemy import SQLAlchemy
 from jinja2 import Template
 from markupsafe import Markup
+
+
+from sqlalchemy import cast, Integer, Text, Column, ForeignKey, literal, null
+from sqlalchemy.orm import sessionmaker, relationship, aliased
+from sqlalchemy.sql import column, label, expression, functions
 from sqlalchemy.ext.hybrid import hybrid_property
-from sqlalchemy.sql import expression, functions
-from werkzeug.utils import redirect
 
+from werkzeug.utils import redirect
 from wtforms import validators
 
 import flask_admin as admin
@@ -91,6 +95,17 @@ class Programminglanguage(db.Model):
         return "{}".format(self.name)
 
 
+class Method(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.String(64))
+    description =  db.Column(db.String(1024))
+    parent_id = db.Column(db.Integer, db.ForeignKey('method.id'))
+    parent = db.relationship('Method', remote_side=[id], backref='children')
+
+    def __str__(self):
+        return "{}".format(self.name)
+
+
 class SoftwareCategory(db.Model):
     id = db.Column(db.Integer, primary_key=True)
     name = db.Column(db.String(120))
@@ -123,7 +138,9 @@ class Software(db.Model):
 
     programminglanguages = db.relationship('Programminglanguage', secondary=software_programminglanguages_table)
 
-    architecture = db.Column(db.Enum('standalone', 'package', 'framework', 'app', 'SaaS', 'other', name='software_types'))
+    architecture = db.Column(db.Enum('standalone', 'package', 'framework', 'app', 'SaaS', 'plugin', 'other', name='software_types'))
+
+    recommandedcitation = db.Column(db.String(120))
 
     def __str__(self):
         return "{}".format(self.name)
@@ -144,6 +161,15 @@ class Link(db.Model):
         return "<a href='#'>{}</a>:{}".format(self.type,self.url)
 
 
+class Reference(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    name = db.Column(db.Unicode(64))
+    cited = db.Column(db.Unicode(64))
+
+    def __str__(self):
+        return "{}".format(self.name)
+
+
 # Flask views
 @app.route('/')
 def index():
@@ -209,12 +235,40 @@ class AdvancedSoftwareView(sqla.ModelView):
                 raise
             flash("Not done")
 
+    @action('advancedexport2', 'AdvancedExport2')
+    def action_advancedexport2(self, ids):
+        try:
+            hierarchy = db.session.query(Method, literal(0).label('level')).filter(Method.parent_id == null()) \
+            .cte(name="hierarchy", recursive=True)
+
+            parent = aliased(hierarchy, name="p")
+            children = aliased(Method, name="c")
+            hierarchy = hierarchy.union_all(
+            db.session.query(
+                children,
+                (parent.c.level + 1).label("level"))
+                .filter(children.parent_id == parent.c.id))
+
+            result = db.session.query(hierarchy.c.level, hierarchy.c.id, hierarchy.c.parent_id, hierarchy.c.name, hierarchy.c.description)\
+                .select_entity_from(hierarchy).order_by(hierarchy.c.id)\
+                .all()
+
+            # Generate sub pages
+            with open('templates/export/MethodsList.jinja2', "r", encoding="utf-8") as file_:
+                template = Template(file_.read())
+            template.stream(methods=result).dump('../digitale-Methoden-wiki/MethodsList.asciidoc', encoding='utf-8')
+            flash("Files generated!")
+        except Exception as ex:
+            if not self.handle_view_exception(ex):
+                raise
+            flash("Not done")
 
 # Create admin
-admin = admin.Admin(app, name='SoftwareTools: digital methods', template_mode='bootstrap3')
+admin = admin.Admin(app, name='digital methods:software-tools', template_mode='bootstrap3')
 
 # Add views
-admin.add_view(AdvancedSoftwareView(Software, db.session, name="SoftwareTool"))
+admin.add_view(AdvancedSoftwareView(Software, db.session, name="Software-Tools"))
+admin.add_view(sqla.ModelView(Method, db.session, name="methods"))
 admin.add_view(sqla.ModelView(Feature, db.session, category="Misc"))
 admin.add_view(sqla.ModelView(License, db.session, category="Misc"))
 admin.add_view(sqla.ModelView(Link, db.session, category="Misc"))
@@ -232,6 +286,168 @@ def build_sample_db():
 
     db.drop_all()
     db.create_all()
+
+    method = Method(id=1,
+                    name="digital methods",
+                    description="",
+                    parent=None)
+    db.session.add(method)
+    method1 = Method(id=2,
+                     name="data mining",
+                     description="",
+                     parent=method)
+    db.session.add(method1)
+
+    method2 = Method(id=3,
+                     name="automated data collection",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method3 = Method(id=4,
+                     name="collect log-data",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method3 = Method(id=5,
+                     name="parsing from api",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method3 = Method(id=6,
+                     name="scraping",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method4 = Method(id=7,
+                     name="scraping (static content)",
+                     description="",
+                     parent=method3)
+    db.session.add(method4)
+    method4 = Method(id=8,
+                     name="scraping (dynamic content)",
+                     description="",
+                     parent=method3)
+    db.session.add(method4)
+    method3 = Method(id=9,
+                     name="crawling",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method2 = Method(id=10,
+                     name="data wrangling",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method3 = Method(id=11,
+                     name="regular expressions",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method3 = Method(id=12,
+                     name="format conversions",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method3 = Method(id=13,
+                     name="language preprocessing",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method2 = Method(id=14, name="information extraction",
+                     description="finding factual information in free text",
+                     parent=method1)
+    db.session.add(method2)
+    method2 = Method(id=15,name="information retrieval",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method2 = Method(id=16,name="statistical analysis",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method3 = Method(id=17,name="frequency analysis",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method3 = Method(id=18,name="classification/machine learning",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method4 = Method(id=19,name="supervised classification",
+                     description="",
+                     parent=method3)
+    db.session.add(method4)
+    method4 = Method(id=20,name="topic models",
+                     description="",
+                     parent=method3)
+    db.session.add(method4)
+    method4 = Method(id=21,name="sentiment analysis",
+                     description="",
+                     parent=method3)
+    db.session.add(method4)
+    method4 = Method(id=22,name="automated narrative, argumentative structures, irony, metaphor detection/extraction",
+                     description="",
+                     parent=method3)
+    db.session.add(method4)
+    method3 = Method(id=23,name="network analysis",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+    method4 = Method(id=24, name="knowledge graph construction",
+                     description="finding factual information in free text",
+                     parent=method3)
+    db.session.add(method4)
+
+    method2 = Method(id=25,name="data visualization",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method3 = Method(id=26,name="dynamic visualizations",
+                     description="",
+                     parent=method2)
+    db.session.add(method3)
+
+    method1 = Method(id=27,name="science practice",
+                     description="",
+                     parent=method)
+    db.session.add(method1)
+    method2 = Method(id=28,name="digital research design",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method2 = Method(id=29,name="collaborative work",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method2 = Method(id=30,name="digital communication",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method1 = Method(id=31,name="statistical modeling",
+                     description="",
+                     parent=method)
+    db.session.add(method1)
+    method2 = Method(id=32,name="regression analysis",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method2 = Method(id=33,name="time-series analysis",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method2 = Method(id=34,name="agent-based modeling",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method2 = Method(id=35,name="digital communication",
+                     description="",
+                     parent=method1)
+    db.session.add(method2)
+    method1 = Method(id=36,name="social complexity modeling/ social simulation",
+                     description="",
+                     parent=method)
+    db.session.add(method1)
+
     lic_unknown = License(name="Unknown")
     lic_bsd = License(name="BSD")
     lic_gpl2 = License(name="GPL", version="2.0")
@@ -254,6 +470,7 @@ def build_sample_db():
     prol_py = Programminglanguage(name="Python")
     prol_cy = Programminglanguage(name="Cython")
     prol_java = Programminglanguage(name="Java")
+    prol_scala = Programminglanguage(name="Scala")
     prol_objc = Programminglanguage(name="Objective-C")
     prol_jupyternb = Programminglanguage(name="Jupyter Notebook")
     prol_js = Programminglanguage(name="Javascript")
@@ -285,6 +502,7 @@ def build_sample_db():
     cat_search = SoftwareCategory(name="search", short_description="information retrieval in large datasets.")
     cat_ocr = SoftwareCategory(name="optical character recognition (OCR)",short_description="OCR is the mechanical or electronic conversion of images of typed, handwritten or printed text into machine-encoded text.")
     cat_oe = SoftwareCategory(name="online experiments", short_description="")
+    cat_agent = SoftwareCategory(name="Agent-based modeling", short_description="")
     cat_misc = SoftwareCategory(name="miscellaneous", short_description="")
 
 
@@ -293,14 +511,14 @@ def build_sample_db():
     db.session.add(cat_int)
 
     tool = Software(name="AWARE",
-                    short_description="",
+                    short_description="'AWARE is an Android framework dedicated to instrument, infer, log and share mobile context information, for application developers, researchers and smartphone users. AWARE captures hardware-, software-, and human-based data. The data is then analyzed using AWARE plugins. They transform data into information you can understand.' link:http://www.awareframework.com/what-is-aware/[Source, visited: 27.02.2019]",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_tracking,
                     architecture="framework",
                     license=lic_apache2,
                     programminglanguages=[prol_java],
-                    price="")
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://www.awareframework.com/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/denzilferreira/aware-client", comment="android"))
@@ -315,8 +533,11 @@ def build_sample_db():
                     softwarecategory=cat_tracking,
                     architecture="framework",
                     license=lic_gpl3,
-                    programminglanguages=[prol_java])
+                    programminglanguages=[prol_java],
+                    price="0",
+                    recommandedcitation="")
     db.session.add(tool)
+    db.session.add(Link(software=tool, type="website", url="http://adrianprelipcean.github.io/", comment="dev"))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/Badger-MEILI",
                         comment="group"))
 
@@ -327,20 +548,37 @@ def build_sample_db():
                     softwarecategory=cat_tracking,
                     architecture="framework",
                     license=lic_apache2,
-                    programminglanguages=[prol_py,prol_java])
+                    programminglanguages=[prol_py,prol_java],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://passivedatakit.org/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/audaciouscode/PassiveDataKit-Django", comment="djangoserver"))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/audaciouscode/PassiveDataKit-Android", comment="android"))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/audaciouscode/PassiveDataKit-iOS", comment="iOS"))
 
+    tool = Software(name="Web Historian - Community Edition",
+                    short_description="Chrome browser extension designed to integrate web browsing history data collection into research projects collecting other types of data from participants (e.g. surveys, in-depth interviews, experiments). It uses client-side D3 visualizations to inform participants about the data being collected during the informed consent process. It allows participants to delete specific browsing data or opt-out of browsing data collection. It directs participants to an online survey once they have reviewed their data and made a choice of whether to participate. It has been used with Qualtrics surveys, but any survey that accepts data from a URL will work. It works with the open source Passive Data Kit (PDK) as the backend for data collection. To successfully upload, you need to fill in the address of your PDK server in the js/app/config.js file.",
+                    developer="Ericka Menchen-Trevino and Chris Karr",
+                    maintainer="Ericka Menchen-Trevino and Chris Karr",
+                    softwarecategory=cat_tracking,
+                    architecture="plugin",
+                    license=lic_gpl3,
+                    programminglanguages=[prol_js],
+                    price="0",
+                    recommandedcitation="Menchen-Trevino, E., & Karr, C. (2018). Web Historian - Community Edition. Zenodo. https://doi.org/10.5281/zenodo.1322782")
+    db.session.add(tool)
+    db.session.add(Link(software=tool, type="website", url="https://doi.org/10.5281/zenodo.1322782", comment="doi"))
+    db.session.add(Link(software=tool, type="website", url="http://www.webhistorian.org", comment=""))
+    db.session.add(Link(software=tool, type="repository", url="https://github.com/WebHistorian/community", comment=""))
+
     tool = Software(name="facepager",
                     developer="Jakob Jünger and Till Keyling",
                     maintainer="Jakob Jünger",
                     softwarecategory=cat_scraping,
                     architecture="package",
                     license=lic_mit,
-                    programminglanguages=[prol_py])
+                    programminglanguages=[prol_py],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="wiki", url="https://github.com/strohne/Facepager", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/strohne/Facepager", comment=""))
@@ -351,7 +589,8 @@ def build_sample_db():
                     softwarecategory=cat_scraping,
                     architecture="package",
                     license=lic_bsd,
-                    programminglanguages=[prol_py])
+                    programminglanguages=[prol_py],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://scrapy.org/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/scrapy/scrapy", comment=""))
@@ -362,18 +601,20 @@ def build_sample_db():
                     softwarecategory=cat_scraping,
                     architecture="package",
                     license=lic_agpl3,
-                    programminglanguages=[prol_r])
+                    programminglanguages=[prol_r],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="repository", url="https://github.com/ropensci/RSelenium", comment=""))
 
     tool = Software(name="AmCAT",
-                    short_description="The Amsterdam Content Analysis Toolkit (AmCAT) is an open source infrastructure that makes it easy to do large-scale automatic and manual content analysis (text analysis) for the social sciences and humanities.",
+                    short_description="'The Amsterdam Content Analysis Toolkit (AmCAT) is an open source infrastructure that makes it easy to do large-scale automatic and manual content analysis (text analysis) for the social sciences and humanities.'",
                     developer="Chris Karr",
                     maintainer="Ju Yeong Kim",
                     softwarecategory=cat_int,
                     architecture="SaaS",
                     license=lic_agpl3,
-                    programminglanguages=[prol_py])
+                    programminglanguages=[prol_py],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://vanatteveldt.com/amcat/", comment="entwickler"))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/amcat/amcat", comment=""))
@@ -386,18 +627,20 @@ def build_sample_db():
                     softwarecategory=cat_int,
                     architecture="standalone",
                     license=lic_prop,
-                    programminglanguages=[])
+                    programminglanguages=[],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://socialdatalab.net/COSMOS", comment=""))
 
     tool = Software(name="CWB",
-                    short_description=" a fast, powerful and extremely flexible corpus querying system",
-                    developer="",
-                    maintainer="",
+                    short_description="CWB, the IMS[Institut für Maschinelle Sprachverarbeitung Stuttgart] Open Corpus Workbench is 'a fast, powerful and extremely flexible corpus querying system.'",
+                    developer="Stefan Evert et al.",
+                    maintainer="Stefan Evert et al.",
                     softwarecategory=cat_int,
                     architecture="framework",
                     license=lic_gpl3,
-                    programminglanguages=[prol_c])
+                    programminglanguages=[prol_c],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://cwb.sourceforge.net/index.php", comment=""))
     db.session.add(Link(software=tool, type="repository", url="http://svn.code.sf.net/p/cwb/code/cwb/trunk", comment="cwb"))
@@ -410,7 +653,8 @@ def build_sample_db():
                     softwarecategory=cat_int,
                     architecture="framework",
                     license=lic_lgpl,
-                    programminglanguages=[prol_java,prol_r])
+                    programminglanguages=[prol_java,prol_r],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://lcm.informatik.uni-leipzig.de/generic.html", comment=""))
 
@@ -421,7 +665,8 @@ def build_sample_db():
                     architecture="SaaS",
                     softwarecategory=cat_int,
                     license=lic_lgpl,
-                    programminglanguages=[prol_java,prol_py,prol_r])
+                    programminglanguages=[prol_java,prol_py,prol_r],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://ilcm.informatik.uni-leipzig.de/", comment=""))
 
@@ -432,29 +677,32 @@ def build_sample_db():
                     softwarecategory=cat_qda,
                     architecture="standalone",
                     license=lic_prop,
-                    programminglanguages=[])
+                    programminglanguages=[],
+                    price="600€/1 User/Perpetual")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://atlasti.com/de/produkt/what-is-atlas-ti/", comment=""))
 
     tool = Software(name="Leximancer",
-                    short_description="Leximancer automatically analyses your text documents to identify the high level concepts in your text documents, delivering the key ideas and actionable insights you need with powerful interactive visualisations and data exports.",
+                    short_description="'Leximancer automatically analyses your text documents to identify the high level concepts in your text documents, delivering the key ideas and actionable insights you need with powerful interactive visualisations and data exports.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_qda,
                     architecture="standalone",
                     license=lic_prop,
-                    programminglanguages=[])
+                    programminglanguages=[],
+                    price="1500 AUD/? User/Perpetual")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://info.leximancer.com/", comment=""))
 
     tool = Software(name="MAXQDA",
-                    short_description="",
+                    short_description="'MAXQDA gehört zu den weltweit führenden und umfangreichsten QDA-Software-Programmen im Bereich der Qualitativen und Mixed-Methods-Forschung. Die Software hilft Ihnen beim Erfassen, Organisieren, Analysieren, Visualisieren und Veröffentlichen Ihrer Daten. Ob Grounded Theory, Literaturreview, explorative Marktforschung, Interviews, Webseitenanalyse oder Surveys: Analysieren Sie was Sie wollen, wie Sie wollen.MAXQDA Analytics Pro ist die erweiterte Version von MAXQDA und enthält neben allen Funktionen für die Qualitative & Mixed Methods-Forschung auch ein Modul für die quantitative Textanalyse (MAXDictio) und ein Modul für die statistische Datenanalyse (MAXQDA Stats)'link:https://www.rrz.uni-hamburg.de/services/software/alphabetisch/maxqda.html[Source, visited: 27.02.2019]",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_qda,
                     architecture="standalone",
                     license=lic_prop,
-                    programminglanguages=[])
+                    programminglanguages=[],
+                    price="Unilizenz")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://www.rrz.uni-hamburg.de/services/software/alphabetisch/maxqda.html", comment="uhh"))
 
@@ -465,7 +713,8 @@ def build_sample_db():
                     softwarecategory=cat_qda,
                     architecture="standalone",
                     license=lic_prop,
-                    programminglanguages=[])
+                    programminglanguages=[],
+                    price="")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://www.qsrinternational.com/nvivo/who-uses-nvivo/academics", comment=""))
 
@@ -504,36 +753,39 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="", comment=""))
 
     tool = Software(name="RQDA",
-                    short_description="It includes a number of standard Computer-Aided Qualitative Data Analysis features. In addition it seamlessly integrates with R, which means that a) statistical analysis on the coding is possible, and b) functions for data manipulation and analysis can be easily extended by writing R functions. To some extent, RQDA and R make an integrated platform for both quantitative and qualitative data analysis.",
+                    short_description="'It includes a number of standard Computer-Aided Qualitative Data Analysis features. In addition it seamlessly integrates with R, which means that a) statistical analysis on the coding is possible, and b) functions for data manipulation and analysis can be easily extended by writing R functions. To some extent, RQDA and R make an integrated platform for both quantitative and qualitative data analysis.'",
                     developer="Ronggui Huang",
                     maintainer="Ronggui Huang",
                     softwarecategory=cat_qda,
                     architecture="package",
                     license=lic_bsd,
-                    programminglanguages=[prol_r])
+                    programminglanguages=[prol_r],
+                    price="")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://rqda.r-forge.r-project.org/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/Ronggui/RQDA", comment=""))
 
     tool = Software(name="TAMS",
-                    short_description="Text Analysis Markup System (TAMS) is both a system of marking documents for qualitative analysis and a series of tools for mining information based on that syntax.",
+                    short_description="'Text Analysis Markup System (TAMS) is both a system of marking documents for qualitative analysis and a series of tools for mining information based on that syntax.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_qda,
                     architecture="standalone",
                     license=lic_gpl2,
-                    programminglanguages=[])
+                    programminglanguages=[],
+                    price="")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://sourceforge.net/projects/tamsys", comment=""))
 
     tool = Software(name="Apache OpenNLP",
-                    short_description="OpenNLP supports the most common NLP tasks, such as tokenization, sentence segmentation, part-of-speech tagging, named entity extraction, chunking, parsing, language detection and coreference resolution.",
+                    short_description="'OpenNLP supports the most common NLP tasks, such as tokenization, sentence segmentation, part-of-speech tagging, named entity extraction, chunking, parsing, language detection and coreference resolution.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_tm,
                     license=lic_apache2,
                     architecture="package",
-                    programminglanguages=[prol_java])
+                    programminglanguages=[prol_java],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://opennlp.apache.org/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="", comment=""))
@@ -545,31 +797,34 @@ def build_sample_db():
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_lgpl,
-                    programminglanguages=[prol_java])
+                    programminglanguages=[prol_java],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://gate.ac.uk/overview.html", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/GateNLP/gate-core", comment=""))
 
     tool = Software(name="Gensim",
-                    short_description="Gensim is a Python library for topic modelling, document indexing and similarity retrieval with large corpora. Target audience is the natural language processing (NLP) and information retrieval (IR) community.",
+                    short_description="'Gensim is a Python library for topic modelling, document indexing and similarity retrieval with large corpora. Target audience is the natural language processing (NLP) and information retrieval (IR) community.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_lgpl,
-                    programminglanguages=[prol_py])
+                    programminglanguages=[prol_py],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://pypi.org/project/gensim/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="", comment=""))
 
     tool = Software(name="NLTK",
-                    short_description="NLTK is a leading platform for building Python programs to work with human language data. It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet, along with a suite of text processing libraries for classification, tokenization, stemming, tagging, parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries, and an active discussion forum.",
+                    short_description="'NLTK is a leading platform for building Python programs to work with human language data. It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet, along with a suite of text processing libraries for classification, tokenization, stemming, tagging, parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries, and an active discussion forum.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_apache2,
-                    programminglanguages=[prol_py])
+                    programminglanguages=[prol_py],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://www.nltk.org/index.html", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/nltk/nltk", comment=""))
@@ -581,7 +836,8 @@ def build_sample_db():
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_bsd,
-                    programminglanguages=[prol_py])
+                    programminglanguages=[prol_py],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://pandas.pydata.org/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/pandas-dev/pandas", comment=""))
@@ -593,19 +849,21 @@ def build_sample_db():
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_gpl3,
-                    programminglanguages=[prol_r])
+                    programminglanguages=[prol_r],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://cran.r-project.org/package=polmineR", comment="cran"))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/PolMine/polmineR", comment=""))
 
     tool = Software(name="quanteda",
-                    short_description="The package is designed for R users needing to apply natural language processing to texts, from documents to final analysis. Its capabilities match or exceed those provided in many end-user software applications, many of which are expensive and not open source. The package is therefore of great benefit to researchers, students, and other analysts with fewer financial resources. While using quanteda requires R programming knowledge, its API is designed to enable powerful, efficient analysis with a minimum of steps. By emphasizing consistent design, furthermore, quanteda lowers the barriers to learning and using NLP and quantitative text analysis even for proficient R programmers.",
+                    short_description="'The package is designed for R users needing to apply natural language processing to texts, from documents to final analysis. Its capabilities match or exceed those provided in many end-user software applications, many of which are expensive and not open source. The package is therefore of great benefit to researchers, students, and other analysts with fewer financial resources. While using quanteda requires R programming knowledge, its API is designed to enable powerful, efficient analysis with a minimum of steps. By emphasizing consistent design, furthermore, quanteda lowers the barriers to learning and using NLP and quantitative text analysis even for proficient R programmers.'",
                     developer="Kenneth Benoit",
                     maintainer="Kenneth Benoit",
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_gpl3,
-                    programminglanguages=[prol_r])
+                    programminglanguages=[prol_r],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://quanteda.io/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/quanteda/quanteda", comment=""))
@@ -617,19 +875,21 @@ def build_sample_db():
                     softwarecategory=cat_tm,
                     architecture="framework",
                     license=lic_agpl3,
-                    programminglanguages=[prol_java])
+                    programminglanguages=[prol_java],
+                    price="")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://rapidminer.com/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/rapidminer/rapidminer-studio", comment=""))
 
     tool = Software(name="spaCy",
-                    short_description=" spaCy excels at large-scale information extraction tasks. It's written from the ground up in carefully memory-managed Cython. Independent research has confirmed that spaCy is the fastest in the world. If your application needs to process entire web dumps, spaCy is the library you want to be using.",
+                    short_description="spaCy 'excels at large-scale information extraction tasks. It's written from the ground up in carefully memory-managed Cython. Independent research has confirmed that spaCy is the fastest in the world. If your application needs to process entire web dumps, spaCy is the library you want to be using.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_mit,
-                    programminglanguages=[prol_cy])
+                    programminglanguages=[prol_cy],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://spacy.io/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/explosion/spaCy", comment=""))
@@ -641,7 +901,8 @@ def build_sample_db():
                     softwarecategory=cat_tm,
                     architecture="framework",
                     license=lic_gpl3,
-                    programminglanguages=[prol_java])
+                    programminglanguages=[prol_java],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="https://stanfordnlp.github.io/CoreNLP/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/stanfordnlp/CoreNLP", comment=""))
@@ -653,20 +914,22 @@ def build_sample_db():
                     softwarecategory=cat_tm,
                     architecture="package",
                     license=lic_gpl3,
-                    programminglanguages=[prol_r])
+                    programminglanguages=[prol_r],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://tm.r-forge.r-project.org/", comment=""))
     db.session.add(Link(software=tool, type="website", url="https://cran.r-project.org/package=tm", comment="cran"))
     db.session.add(Link(software=tool, type="repository", url="", comment=""))
 
     tool = Software(name="xtas",
-                    short_description="the eXtensible Text Analysis Suite(xtas) is a collection of natural language processing and text mining tools, brought together in a single software package with built-in distributed computing and support for the Elasticsearch document store.",
+                    short_description="the eXtensible Text Analysis Suite(xtas) 'is a collection of natural language processing and text mining tools, brought together in a single software package with built-in distributed computing and support for the Elasticsearch document store.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_tm,
                     architecture="framework",
                     license=lic_apache2,
-                    programminglanguages=[prol_py])
+                    programminglanguages=[prol_py],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://nlesc.github.io/xtas/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/NLeSC/xtas", comment=""))
@@ -684,7 +947,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="https://github.com/mimno/Mallet", comment=""))
 
     tool = Software(name="TOME",
-                    short_description="TOME is a tool to support the interactive exploration and visualization of text-based archives, supported by a Digital Humanities Startup Grant from the National Endowment for the Humanities (Lauren Klein and Jacob Eisenstein, co-PIs). Drawing upon the technique of topic modeling—a machine learning method for identifying the set of topics, or themes, in a document set—our tool allows humanities scholars to trace the evolution and circulation of these themes across networks and over time.",
+                    short_description="'TOME is a tool to support the interactive exploration and visualization of text-based archives, supported by a Digital Humanities Startup Grant from the National Endowment for the Humanities (Lauren Klein and Jacob Eisenstein, co-PIs). Drawing upon the technique of topic modeling—a machine learning method for identifying the set of topics, or themes, in a document set—our tool allows humanities scholars to trace the evolution and circulation of these themes across networks and over time.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_topic,
@@ -696,19 +959,20 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="https://github.com/GeorgiaTechDHLab/TOME/", comment=""))
 
     tool = Software(name="Stm",
-                    short_description="The Structural Topic Model (STM) allows researchers to estimate topic models with document-level covariates. The package also includes tools for model selection, visualization, and estimation of topic-covariate regressions. Methods developed in Roberts et al (2014) <doi:10.1111/ajps.12103> and Roberts et al (2016) <doi:10.1080/01621459.2016.1141684>.",
+                    short_description="'The Structural Topic Model (STM) allows researchers to estimate topic models with document-level covariates. The package also includes tools for model selection, visualization, and estimation of topic-covariate regressions. Methods developed in Roberts et al (2014) <doi:10.1111/ajps.12103> and Roberts et al (2016) <doi:10.1080/01621459.2016.1141684>.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_topic,
                     architecture="package",
                     license=lic_mit,
-                    programminglanguages=[prol_r])
+                    programminglanguages=[prol_r],
+                    price="0")
     db.session.add(tool)
     db.session.add(Link(software=tool, type="website", url="http://structuraltopicmodel.com", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/bstewart/stm", comment=""))
 
     tool = Software(name="lexicoder",
-                    short_description="Lexicoder performs simple deductive content analyses of any kind of text, in almost any language. All that is required is the text itself, and a dictionary. Our own work initially focused on the analysis of newspaper stories during election campaigns, and both television and newspaper stories about public policy issues. The software can deal with almost any text, however, and lots of it. Our own databases typically include up to 100,000 news stories. Lexicoder processes these data, even with a relatively complicated coding dictionary, in about fifteen minutes. The software has, we hope, a wide range of applications in the social sciences. It is not the only software that conducts content analysis, of course - there are many packages out there, some of which are much more sophisticated than this one. The advantage to Lexicoder, however, is that it can run on any computer with a recent version of Java (PC or Mac), it is very simple to use, it can deal with huge bodies of data, it can be called from R as well as from the Command Line, and its free.",
+                    short_description="'Lexicoder performs simple deductive content analyses of any kind of text, in almost any language. All that is required is the text itself, and a dictionary. Our own work initially focused on the analysis of newspaper stories during election campaigns, and both television and newspaper stories about public policy issues. The software can deal with almost any text, however, and lots of it. Our own databases typically include up to 100,000 news stories. Lexicoder processes these data, even with a relatively complicated coding dictionary, in about fifteen minutes. The software has, we hope, a wide range of applications in the social sciences. It is not the only software that conducts content analysis, of course - there are many packages out there, some of which are much more sophisticated than this one. The advantage to Lexicoder, however, is that it can run on any computer with a recent version of Java (PC or Mac), it is very simple to use, it can deal with huge bodies of data, it can be called from R as well as from the Command Line, and its free.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_senti,
@@ -719,7 +983,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="website", url="http://www.lexicoder.com/index.html", comment=""))
 
     tool = Software(name="OpinionFinder",
-                    short_description="OpinionFinder is a system that processes documents and automatically identifies subjective sentences as well as various aspects of subjectivity within sentences, including agents who are sources of opinion, direct subjective expressions and speech events, and sentiment expressions. OpinionFinder was developed by researchers at the University of Pittsburgh, Cornell University, and the University of Utah. In addition to OpinionFinder, we are also releasing the automatic annotations produced by running OpinionFinder on a subset of the Penn Treebank.",
+                    short_description="'OpinionFinder is a system that processes documents and automatically identifies subjective sentences as well as various aspects of subjectivity within sentences, including agents who are sources of opinion, direct subjective expressions and speech events, and sentiment expressions. OpinionFinder was developed by researchers at the University of Pittsburgh, Cornell University, and the University of Utah. In addition to OpinionFinder, we are also releasing the automatic annotations produced by running OpinionFinder on a subset of the Penn Treebank.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_senti,
@@ -731,7 +995,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="", comment=""))
 
     tool = Software(name="Readme",
-                    short_description="The ReadMe software package for R takes as input a set of text documents (such as speeches, blog posts, newspaper articles, judicial opinions, movie reviews, etc.), a categorization scheme chosen by the user (e.g., ordered positive to negative sentiment ratings, unordered policy topics, or any other mutually exclusive and exhaustive set of categories), and a small subset of text documents hand classified into the given categories. ",
+                    short_description="'The ReadMe software package for R takes as input a set of text documents (such as speeches, blog posts, newspaper articles, judicial opinions, movie reviews, etc.), a categorization scheme chosen by the user (e.g., ordered positive to negative sentiment ratings, unordered policy topics, or any other mutually exclusive and exhaustive set of categories), and a small subset of text documents hand classified into the given categories.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_senti,
@@ -742,7 +1006,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="website", url="https://gking.harvard.edu/readme", comment=""))
 
     tool = Software(name="Gephi",
-                    short_description="Gephi is an award-winning open-source platform for visualizing and manipulating large graphs.",
+                    short_description="'Gephi is an award-winning open-source platform for visualizing and manipulating large graphs.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_visu,
@@ -753,8 +1017,20 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="website", url="https://gephi.org/", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/gephi/gephi/", comment=""))
 
+    tool = Software(name="sigma.js",
+                    short_description="'Sigma is a JavaScript library dedicated to graph drawing. It makes easy to publish networks on Web pages, and allows developers to integrate network exploration in rich Web applications.'",
+                    developer="Alexis Jacomy",
+                    maintainer="Alexis Jacomy",
+                    softwarecategory=cat_visu,
+                    architecture="package",
+                    license=lic_mit,
+                    programminglanguages=[prol_js])
+    db.session.add(tool)
+    db.session.add(Link(software=tool, type="website", url="http://sigmajs.org/", comment=""))
+    db.session.add(Link(software=tool, type="repository", url="https://github.com/jacomyal/sigma.js", comment=""))
+
     tool = Software(name="scikit-image",
-                    short_description="scikit-image is a collection of algorithms for image processing. It is available free of charge and free of restriction. We pride ourselves on high-quality, peer-reviewed code, written by an active community of volunteers.",
+                    short_description="'scikit-image is a collection of algorithms for image processing. It is available free of charge and free of restriction. We pride ourselves on high-quality, peer-reviewed code, written by an active community of volunteers.'",
                     developer="Stéfan van der Walt, Johannes L. Schönberger, Juan Nunez-Iglesias, François Boulogne, Joshua D. Warner, Neil Yager, Emmanuelle Gouillart, Tony Yu, and the scikit-image contributors",
                     maintainer="Stéfan van der Walt, Johannes L. Schönberger, Juan Nunez-Iglesias, François Boulogne, Joshua D. Warner, Neil Yager, Emmanuelle Gouillart, Tony Yu, and the scikit-image contributors",
                     softwarecategory=cat_visu,
@@ -766,7 +1042,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="https://github.com/scikit-image/scikit-image", comment=""))
 
     tool = Software(name="CATMA",
-                    short_description="CATMA (Computer Assisted Text Markup and Analysis) is a practical and intuitive tool for text researchers. In CATMA users can combine the hermeneutic, ‘undogmatic’ and the digital, taxonomy based approach to text and corpora—as a single researcher, or in real-time collaboration with other team members.",
+                    short_description="'CATMA (Computer Assisted Text Markup and Analysis) is a practical and intuitive tool for text researchers. In CATMA users can combine the hermeneutic, ‘undogmatic’ and the digital, taxonomy based approach to text and corpora—as a single researcher, or in real-time collaboration with other team members.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_kollab_anno,
@@ -874,7 +1150,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="https://github.com/nmecsys/nowcasting", comment=""))
 
     tool = Software(name="AutoMap",
-                    short_description="AutoMap enables the extraction of information from texts using Network Text Analysis methods. AutoMap supports the extraction of several types of data from unstructured documents. The type of information that can be extracted includes: content analytic data (words and frequencies), semantic network data (the network of concepts), meta-network data (the cross classification of concepts into their ontological category such as people, places and things and the connections among these classified concepts), and sentiment data (attitudes, beliefs). Extraction of each type of data assumes the previously listed type of data has been extracted.",
+                    short_description="'AutoMap enables the extraction of information from texts using Network Text Analysis methods. AutoMap supports the extraction of several types of data from unstructured documents. The type of information that can be extracted includes: content analytic data (words and frequencies), semantic network data (the network of concepts), meta-network data (the cross classification of concepts into their ontological category such as people, places and things and the connections among these classified concepts), and sentiment data (attitudes, beliefs). Extraction of each type of data assumes the previously listed type of data has been extracted.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_net,
@@ -919,7 +1195,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="website", url="http://mrvar.fdv.uni-lj.si/pajek/", comment=""))
 
     tool = Software(name="NetworkX",
-                    short_description="Data structures for graphs, digraphs, and multigraphs Many standard graph algorithms Network structure and analysis measures Generators for classic graphs, random graphs, and synthetic networks Nodes can be 'anything' (e.g., text, images, XML records) Edges can hold arbitrary data (e.g., weights, time-series) Open source 3-clause BSD license Well tested with over 90% code coverage Additional benefits from Python include fast prototyping, easy to teach, and multi-platform",
+                    short_description="'Data structures for graphs, digraphs, and multigraphs Many standard graph algorithms Network structure and analysis measures Generators for classic graphs, random graphs, and synthetic networks Nodes can be 'anything' (e.g., text, images, XML records) Edges can hold arbitrary data (e.g., weights, time-series) Open source 3-clause BSD license Well tested with over 90% code coverage Additional benefits from Python include fast prototyping, easy to teach, and multi-platform.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_net,
@@ -931,7 +1207,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="", comment=""))
 
     tool = Software(name="UCINET",
-                    short_description="UCINET 6 for Windows is a software package for the analysis of social network data. It was developed by Lin Freeman, Martin Everett and Steve Borgatti. It comes with the NetDraw network visualization tool.",
+                    short_description="'UCINET 6 for Windows is a software package for the analysis of social network data. It was developed by Lin Freeman, Martin Everett and Steve Borgatti. It comes with the NetDraw network visualization tool.'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_net,
@@ -976,7 +1252,7 @@ def build_sample_db():
     db.session.add(Link(software=f4analyse, type="website", url="https://www.audiotranskription.de/f4-analyse", comment=""))
 
     tool = Software(name="EXMARaLDA",
-                    short_description="EXMARaLDA ist ein System für das computergestützte Arbeiten mit (vor allem) mündlichen Korpora. Es besteht aus einem Transkriptions- und Annotationseditor (Partitur-Editor), einem Tool zum Verwalten von Korpora (Corpus-Manager) und einem Such- und Analysewerkzeug (EXAKT).",
+                    short_description="'EXMARaLDA ist ein System für das computergestützte Arbeiten mit (vor allem) mündlichen Korpora. Es besteht aus einem Transkriptions- und Annotationseditor (Partitur-Editor), einem Tool zum Verwalten von Korpora (Corpus-Manager) und einem Such- und Analysewerkzeug (EXAKT).'",
                     developer="",
                     maintainer="",
                     softwarecategory=cat_transkript,
@@ -988,7 +1264,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="https://github.com/EXMARaLDA/exmaralda", comment=""))
 
     tool = Software(name="tesseract",
-                    short_description="Tesseract is an open source text recognizer (OCR) Engine, available under the Apache 2.0 license. It can be used directly, or (for programmers) using an API to extract printed text from images. It supports a wide variety of languages.",
+                    short_description="'Tesseract is an open source text recognizer (OCR) Engine, available under the Apache 2.0 license. It can be used directly, or (for programmers) using an API to extract printed text from images. It supports a wide variety of languages.'",
                     developer="Google, HP Inc.",
                     maintainer="Ray Smith u. a. ",
                     softwarecategory=cat_ocr,
@@ -999,7 +1275,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="https://github.com/tesseract-ocr/tesseract", comment=""))
 
     tool = Software(name="nodeGame",
-                    short_description="NodeGame is a free, open source JavaScript/HTML5 framework for conducting synchronous experiments online and in the lab directly in the browser window. It is specifically designed to support behavioral research along three dimensions: larger group sizes, real-time (but also discrete time) experiments, batches of simultaneous experiments.",
+                    short_description="'NodeGame is a free, open source JavaScript/HTML5 framework for conducting synchronous experiments online and in the lab directly in the browser window. It is specifically designed to support behavioral research along three dimensions: larger group sizes, real-time (but also discrete time) experiments, batches of simultaneous experiments.'",
                     developer="Stefan Balietti",
                     maintainer="Stefan Balietti",
                     softwarecategory=cat_oe,
@@ -1011,7 +1287,7 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="repository", url="https://github.com/nodeGame", comment=""))
 
     tool = Software(name="scikit-learn",
-                    short_description="Scikit-learn is a free software machine learning library for the Python programming language. It features various classification, regression and clustering algorithms including support vector machines, random forests, gradient boosting, k-means and DBSCAN, and is designed to interoperate with the Python numerical and scientific libraries NumPy and SciPy.",
+                    short_description="'Scikit-learn is a free software machine learning library for the Python programming language. It features various classification, regression and clustering algorithms including support vector machines, random forests, gradient boosting, k-means and DBSCAN, and is designed to interoperate with the Python numerical and scientific libraries NumPy and SciPy.'",
                     developer="Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V. and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P. and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.",
                     maintainer="Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V. and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P. and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.",
                     softwarecategory=cat_misc,
@@ -1022,6 +1298,31 @@ def build_sample_db():
     db.session.add(Link(software=tool, type="website", url="https://scikit-learn.org/stable/index.html", comment=""))
     db.session.add(Link(software=tool, type="repository", url="https://github.com/scikit-learn/scikit-learn", comment=""))
 
+    tool = Software(name="NetLogo",
+                    short_description="'NetLogo is a multi-agent programmable modeling environment. It is used by many tens of thousands of students, teachers and researchers worldwide. It also powers HubNet participatory simulations.'",
+                    developer="Uri Wilensky",
+                    maintainer="Uri Wilensky",
+                    softwarecategory=cat_agent,
+                    architecture="package",
+                    license=lic_unknown,
+                    programminglanguages=[prol_java, prol_scala])
+    db.session.add(tool)
+    db.session.add(Link(software=tool, type="website", url="http://ccl.northwestern.edu/netlogo/", comment=""))
+    db.session.add(Link(software=tool, type="repository", url="https://github.com/NetLogo/NetLogo", comment=""))
+
+    tool = Software(name="spades",
+                    short_description="",
+                    developer="",
+                    maintainer="",
+                    softwarecategory=cat_misc,
+                    architecture="package",
+                #    license=,
+                    programminglanguages=[prol_r])
+    db.session.add(tool)
+    db.session.add(Link(software=tool, type="website", url="http://spades.predictiveecology.org/", comment=""))
+    db.session.add(Link(software=tool, type="repository", url="", comment=""))
+
+
     '''
      tool = Software(name="",
                      short_description="",
diff --git a/sample_db.sqlite b/sample_db.sqlite
index 71c57ac22da4c8b03f75d19b5e73b215f671f0a8..4b40f87ea9ff54c043f2eef9a97d635556d650e5 100644
GIT binary patch
delta 12516
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

delta 6245
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
OUu4JV#-dr8kpTda=Ncmb

diff --git a/templates/export/MethodsList.jinja2 b/templates/export/MethodsList.jinja2
new file mode 100644
index 0000000..701d368
--- /dev/null
+++ b/templates/export/MethodsList.jinja2
@@ -0,0 +1,10 @@
+:toc:
+:toclevels: 8
+:toc-title: Table of contents (work in progress: this list is preliminary and will be updated continuously)
+:sectnums:
+:sectnumlevels: 8
+
+{% for method in methods %}
+{% for l in range(method.level+1) %}={% endfor %} {{ method.name }}
+{{method.description}}
+{% endfor %}
\ No newline at end of file
-- 
GitLab