The application's Perl code lives under lib/Kastalia/. Main.pm defines almost every HTTP route -- what URL does what. Core.pm, TT.pm, SelectorQueries.pm and API.pm have no package statement of their own: they are require'd straight into Main.pm's namespace, so every helper function they define (addKnot, addBound, addAttribute, the various graph-query helpers used by templates, and so on) is directly callable, unqualified, from anywhere in that merged namespace -- effectively one large shared toolbox rather than several separate modules. User.pm is the one exception that keeps its own package Kastalia::User, for the LDAP-backed account/login logic, while still sharing the same Dancer2 app context.
Dancer2 itself handles routing, sessions (backed by Memcached) and the Template::Toolkit rendering described in the Frontend section.
The
application
'
s
Perl
code
lives
under
lib
/
Kastalia
/.
Main
.
pm
defines
almost
every
HTTP
route
--
what
URL
does
what
.
Core
.
pm
''
TT
.
pm
''
SelectorQueries
.
pm
and
API
.
pm
have
no
package
statement
of
their
own
:
they
are
require
'
d
straight
into
Main
.
pm
'
s
namespace
''
so
every
helper
function
they
define
(
addKnot
''
addBound
''
addAttribute
''
the
various
graph
-
query
helpers
used
by
templates
''
and
so
on
)
is
directly
callable
''
unqualified
''
from
anywhere
in
that
merged
namespace
--
effectively
one
large
shared
toolbox
rather
than
several
separate
modules
.
User
.
pm
is
the
one
exception
that
keeps
its
own
package
Kastalia
::
User
''
for
the
LDAP
-
backed
account
/
login
logic
''
while
still
sharing
the
same
Dancer2
app
context
.<
br
><
br
>
Dancer2
itself
handles
routing
''
sessions
(
backed
by
Memcached
)
and
the
Template
::
Toolkit
rendering
described
in
the
Frontend
section
.
Two tables carry almost the entire system: knots(knot_id, knot_name, knot_content, attributes hstore) and bounds(bound_id, sub, predicate, obj, ord, bound_creator).
attributes is a Postgres hstore column -- an open-ended set of key/value string pairs -- rather than a fixed set of typed columns. This is what lets a knot carry wildly different metadata depending on what it's being used for: a presentation knot might have ogg_url and presentation_timeline; an image knot an img_url; a person knot an age or voice. No schema migration is needed to introduce a new attribute -- any route can simply start writing a new key.
predicate, by contrast, is a proper Postgres ENUM type, not a free string -- a closed, explicit list of the relation kinds the graph currently understands (is_parent, contains, is_member, is_uttered_as, illustrates, translates, echoes, is_linked, and a handful of others). Extending the vocabulary means explicitly adding a new value to that enum (ALTER TYPE predicate ADD VALUE ...) -- a small deliberate act, not an accident of someone typing a slightly different string.
433
Two
tables
carry
almost
the
entire
system
:
knots
(
knot
id
''
knot
name
''
knot
content
''
attributes
hstore
)
and
bounds
(
bound
id
''
sub
''
predicate
''
obj
''
ord
''
bound
creator
).<
br
><
br
>
attributes
is
a
Postgres
hstore
column
--
an
open
-
ended
set
of
key
/
value
string
pairs
--
rather
than
a
fixed
set
of
typed
columns
.
This
is
what
lets
a
knot
carry
wildly
different
metadata
depending
on
what
it
'
s
being
used
for
:
a
presentation
knot
might
have
ogg
url
and
presentation
timeline
;
an
image
knot
an
img
url
;
a
person
knot
an
age
or
voice
.
No
schema
migration
is
needed
to
introduce
a
new
attribute
--
any
route
can
simply
start
writing
a
new
key
.<
br
><
br
>
predicate
''
by
contrast
''
is
a
proper
Postgres
ENUM
type
''
not
a
free
string
--
a
closed
''
explicit
list
of
the
relation
kinds
the
graph
currently
understands
(
is
parent
''
contains
''
is
member
''
is
uttered
as
''
illustrates
''
translates
''
echoes
''
is
linked
''
and
a
handful
of
others
).
Extending
the
vocabulary
means
explicitly
adding
a
new
value
to
that
enum
(
ALTER
TYPE
predicate
ADD
VALUE
...)
--
a
small
deliberate
act
''
not
an
accident
of
someone
typing
a
slightly
different
string
.
×
- You start the recording with a start button (You can click on it, touch it, or simply move Your finger/cursor over it).
- Subsequently, You move the finger/cursor over the first syllable/word. You pronounce the segment only when its background has green color.
- You gradually progress from syllable to syllable and segment to segment. You always start pronouncing certain segment only when it is green.
- Note that accentuated & long syllables are marked with blue color, while short/non-accentuated syllables are marked with green color.
- After You are done with the last syllable You move Your finger towards the stop button. Then you can playback the whole recording, when you are satisfied you click on "Upload" and the next text appears.
×
In order to be fully compliant with European data-protection Law, we need Your explicit consent regarding use of Your voice data. Please choose one among following consent types:
- Do not upload :: You do not give us Your consent. Thus, no data will be uploaded from Your browser to our server. But You can still use the interface for testing purposes.
- Only speech-to-text-models :: Your recordings will become part of the corpus from which automatic speech recognition (ASR) models will be trained. Corpus itself will not be published but the final model will be published.
- Only text-to-speech :: Similar to previous option but this time, the resulting model will not be used for ASR but for synthesis of artificial voices.
- STT & TTS :: Both ASR and voice synthesis models could be trained from datasets containing Your recordings. Again, the recordings themselves will not be published.
- Public Dataset :: Your recordings will become part of a publicly available dataset. This is the most permissive option.
Note that in all cases, Your recordings will be anonymized and asides voluntary gender / age / zodiac sign / mother language information no metadata is collected.