diff options
author | Smári McCarthy <smari@hilbert.(none)> | 2009-11-25 15:30:42 +0000 |
---|---|---|
committer | Smári McCarthy <smari@hilbert.(none)> | 2009-11-25 15:30:42 +0000 |
commit | 5e2997288fe03a1209dd5514ee99d7e176f06039 (patch) | |
tree | 60e383199e2631526f74b8731bca77069bfb11ca | |
parent | abf5e252a4647992c794da86355d624f532f579e (diff) | |
parent | b9eec2fa84604f9f697972d413bf89f32c5c015c (diff) | |
download | tangiblebit-5e2997288fe03a1209dd5514ee99d7e176f06039.tar.gz tangiblebit-5e2997288fe03a1209dd5514ee99d7e176f06039.zip |
Merge branch 'master' of git@tangiblebit.com:tangiblebit
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | data/types/basetypes.decl | 33 | ||||
-rw-r--r-- | data/types/object.decl | 141 | ||||
-rw-r--r-- | doc/dev.rst | 3 | ||||
-rw-r--r-- | doc/formats.html | 465 | ||||
-rw-r--r-- | doc/formats.rst | 195 | ||||
-rw-r--r-- | doc/objects.html | 859 | ||||
-rw-r--r-- | doc/objects.rst | 435 | ||||
-rw-r--r-- | doc/tb.rst | 12 | ||||
-rw-r--r-- | server/locations/views.py | 27 | ||||
-rw-r--r-- | server/locations/xmlrpc.py | 9 | ||||
-rw-r--r-- | server/objects/models.py | 8 | ||||
-rw-r--r-- | server/objects/views.py | 19 | ||||
-rw-r--r-- | server/urls.py | 1 |
14 files changed, 2205 insertions, 4 deletions
@@ -1,3 +1,5 @@ *.pyc +*~ +.*.swp tangiblebit.sqlite3 *.pdf diff --git a/data/types/basetypes.decl b/data/types/basetypes.decl new file mode 100644 index 0000000..07cfcdd --- /dev/null +++ b/data/types/basetypes.decl @@ -0,0 +1,33 @@ +# The basic types that can be used for atomic fields. Types not defined +# here are complex types, made up of several atomic or complex types. + +int: "An integer number. External form: as in JSON."; + +float: "A floating point number. External form: as in JSON."; + +bool: 'A Boolean value, either "true" or "false".'; + +string: + """A string. Use this base type for free-form strings that are not meant + to be localized. Strings can contain arbitrary Unicode characters."""; + +timestamp: + """A point in time. External form: like the `YAML timestamp + <http://yaml.org/type/timestamp.html>`_ type."""; + +identifier(string): + "An identifier, made up of alphanumeric characters and underscores."; + +freetext(string): + "Text that can be localized (translated in other languages)."; + +formattedtext(freetext): + "A longer block of text that can contain formatting."; + +file(string): "A pointer to a file (stored externally)."; + +# Unit types + +length(float): "A length, measured by default in meter (m)."; + +mass(float): "A mass, measured by default in kilogram (kg)."; diff --git a/data/types/object.decl b/data/types/object.decl new file mode 100644 index 0000000..e34c874 --- /dev/null +++ b/data/types/object.decl @@ -0,0 +1,141 @@ +Object { + uri: "http://tangiblebit.com/cat/object"; + desc: "The root of the object hierarchy"; + + # Required properties + req { + name(freetext): "An informal name of the object."; + + uri(string): + """An URI uniquely identifying the object; it's a good idea (but not + required) to use a HTTP URI and set up a web page at the specified + location, where interested users can find information on the object + and download it. Sample: http://example.com/design/coffeemaker if you + own the example.com domain."""; + + summary(freetext): + """A short (one line) description of what the object is and what it + can be used for."""; + + license(string): + """The license under which the object is made available (must be + compatible with CC-SA-BY or a free software/open source license in + order to allow inclusion in the TB object database). On the TBit + website there is controlled vocabulary of license names that should + be used in this field and in the *softwareLicense* field."""; + } + + # Optional properties + opt { + description(formattedtext): + "A longer description of the object."; + + lastModified(timestamp): + """Timestamp showing when the object metadata or the files or + processes connected with the object where last modified."""; + + weight(mass): + "The weight of the object (set to 0 if this is a non-material object)."; + + width(length): + """The total width of the object, when fitting it into a box (0 if + this is a non-material object)."""; + + depth(length): + """The total depth of the object, when fitting it into a box (0 if + this is a non-material object)."""; + + height(length): + """The total height of the object, when fitting it into a box (0 if + this is a non-material object)."""; + + softwareLicense(string): + """The license under which the software related to the object is made + available (must be compatible with CC-SA-BY or a free software/open + source license in order to allow inclusion in the TB object + database). If omitted, the value given in the *license* field is used + instead."""; + } + + # Properties occurring once or more + reqlist { + category(identifier): "List of categories the object belongs to."; + + author(string): "List of the people which created/packaged the object."; + + maintainer(string): + "List of people to contact regarding questions about the object."; + + replaces(string): + "List of object URIs this object is meant to replace/make obsolete"; + } + + # Properties occurring any number of times + optlist { + thumbnail(File): + """A list of small visual depictions of the object (pointers to image + files)."""; + + file(File): "List of files associated with the object."; + + process(Process): "List of processes associated with the object."; + } + + +# The complex types used in Object declarations + +File { + + req { # Required + role(string): + """The role of the file in regard to the object, e.g. "depiction" + (audio/visual of the object, e.g. a photo, drawing, or movie), "faq", + "whitepaper". On the TBit website there is controlled vocabulary of + recommended values for this field. Note: files such as "manual" + shouldn't be stored here; rather, they should be associated with a + *use process* (cf. below)."""; + + name(string): "The name of the file."; + + mimetype(string): "The MIME type."; + } + + opt { # Optional + description(freetext): + "A (preferably short) description of the file and its purpose"; + } +} + +Process { + req { # Required + role(string): + """The role of the process in regard to the object, one of + + * build: how to build/produce the object. + * setup: how to setup the object prior to using it (comes between + build and usage, and can optionally later be repeated when + necessary.) Sample: program channel list on a TV set. + * use: how to use the object, in general or for some specific + purpose. + * dismantle: how to dismantle/disassemble the object. + * maintain: how to maintain the object--describes operations that + need to be performed regularly or occasionally to keep the object + in good order. Sample: change oil in a car. + * repair: how to repair the object or some parts of it. + * replace: how to replace same part of the object."""; + + process(string): "The URI of the process."; + + software(bool): + """If true, this file is licensed under the conditions specified in + the *softwareLicense* field, otherwise under the conditions of the + *license* field. This field is only used to provide licensing + information (it does not matter whether the file really contains + software)."""; + + description(freetext): + """A (preferably short) description of the process in relation to the + object."""; + + } +} diff --git a/doc/dev.rst b/doc/dev.rst new file mode 100644 index 0000000..f2551d2 --- /dev/null +++ b/doc/dev.rst @@ -0,0 +1,3 @@ +================================ +Coding Style & Development Notes +================================ diff --git a/doc/formats.html b/doc/formats.html new file mode 100644 index 0000000..e6d8aa5 --- /dev/null +++ b/doc/formats.html @@ -0,0 +1,465 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" /> +<title>Formats and Languages</title> +<style type="text/css"> + +/* +:Author: David Goodger (goodger@python.org) +:Id: $Id: html4css1.css 5196 2007-06-03 20:25:28Z wiemann $ +:Copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. + +See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to +customize this style sheet. +*/ + +/* used to remove borders from tables and images */ +.borderless, table.borderless td, table.borderless th { + border: 0 } + +table.borderless td, table.borderless th { + /* Override padding for "table.docutils td" with "! important". + The right padding separates the table cells. */ + padding: 0 0.5em 0 0 ! important } + +.first { + /* Override more specific margin styles with "! important". */ + margin-top: 0 ! important } + +.last, .with-subtitle { + margin-bottom: 0 ! important } + +.hidden { + display: none } + +a.toc-backref { + text-decoration: none ; + color: black } + +blockquote.epigraph { + margin: 2em 5em ; } + +dl.docutils dd { + margin-bottom: 0.5em } + +/* Uncomment (and remove this text!) to get bold-faced definition list terms +dl.docutils dt { + font-weight: bold } +*/ + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.admonition, div.attention, div.caution, div.danger, div.error, +div.hint, div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.admonition p.admonition-title, div.hint p.admonition-title, +div.important p.admonition-title, div.note p.admonition-title, +div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +/* Uncomment (and remove this text!) to get reduced vertical space in + compound paragraphs. +div.compound .compound-first, div.compound .compound-middle { + margin-bottom: 0.5em } + +div.compound .compound-last, div.compound .compound-middle { + margin-top: 0.5em } +*/ + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em ; + margin-right: 2em } + +div.footer, div.header { + clear: both; + font-size: smaller } + +div.line-block { + display: block ; + margin-top: 1em ; + margin-bottom: 1em } + +div.line-block div.line-block { + margin-top: 0 ; + margin-bottom: 0 ; + margin-left: 1.5em } + +div.sidebar { + margin: 0 0 0.5em 1em ; + border: medium outset ; + padding: 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, +h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { + margin-top: 0.4em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr.docutils { + width: 75% } + +img.align-left { + clear: left } + +img.align-right { + clear: right } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.attribution { + text-align: right ; + margin-left: 50% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.rubric { + font-weight: bold ; + font-size: larger ; + color: maroon ; + text-align: center } + +p.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +span.section-subtitle { + /* font-size relative to parent (h1..h6 element) */ + font-size: 80% } + +table.citation { + border-left: solid 1px gray; + margin-left: 1px } + +table.docinfo { + margin: 2em 4em } + +table.docutils { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.footnote { + border-left: solid 1px black; + margin-left: 1px } + +table.docutils td, table.docutils th, +table.docinfo td, table.docinfo th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +table.docutils th.field-name, table.docinfo th.docinfo-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap ; + padding-left: 0 } + +h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, +h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { + font-size: 100% } + +ul.auto-toc { + list-style-type: none } + +</style> +</head> +<body> +<div class="document" id="formats-and-languages"> +<h1 class="title">Formats and Languages</h1> + +<p>The formats and languages used by Tangible Bit are explained in English and +formally defined in EBNF. TODO extract <tt class="docutils literal"><span class="pre">::</span></tt> blocks and use e.g pyparsing +to autogenerate parsers.</p> +<div class="section" id="ebnf-grammar"> +<h2>EBNF Grammar</h2> +<p>We use an EBNF notation that is identical to the <a class="reference external" href="http://www.w3.org/TR/xml/#sec-notation">EBNF notation used in the +XML specification</a>, except that +we use <tt class="docutils literal"><span class="pre">symbol:</span> <span class="pre">expression;</span></tt> instead of <tt class="docutils literal"><span class="pre">symbol</span> <span class="pre">::=</span> <span class="pre">expression</span></tt> to +define symbols.</p> +</div> +<div class="section" id="predefined-rules"> +<h2>Predefined Rules</h2> +<p>The following EBNF rules are assumed to be predefined and not formally +defined in this document:</p> +<dl class="docutils"> +<dt>Char</dt> +<dd>Any Unicode character</dd> +<dt>UnicodeLetter</dt> +<dd>A character that has the "letter" property in the Unicode database</dd> +<dt>CR</dt> +<dd>a carriage return character (#x0D)</dd> +<dt>LF</dt> +<dd>a line feed character (#x0A)</dd> +</dl> +</div> +<div class="section" id="declarations-language-decl"> +<h2>Declarations Language (DecL)</h2> +<p>A simple, easily writable, readable, and parsable format for declaring +things, used by Tangible Bit for various purposes.</p> +<p>There are four kinds of <em>atoms</em>: <em>strings</em>, <em>numbers</em>, <em>identifier +expressions</em>, and <em>literals</em>:</p> +<pre class="literal-block"> +Atom: String | Number | IdentifierExpression | Literal; +</pre> +<p>There are three types of <em>strings</em>: <em>full-quoted</em> (enclosed in full +quotation marks), <em>half-quoted</em> (enclosed in half quotation marks), and +<em>triple-quoted</em> (enclosed in pairs of three matching full or half quotes):</p> +<pre class="literal-block"> +String: FullQuotedString | HalfQuotedString | TripleQuotedString; +</pre> +<p><em>Full-quoted strings</em> are sequences of arbitrary <em>inline characters</em>, +enclosed between full quotation marks. Full quotation marks within the +string <em>must</em> be backslash-escaped, literal backslashes and half quotation +marks <em>may</em> be backslash-escaped (a literal backslash must be escaped if it +occurs before another backslash or immediately before the end of the +string); backslashes before any other characters are left in the string:</p> +<pre class="literal-block"> +FullQuotedString: '"' (InlineChar - ["\] | "\" InlineChar)* '"'; +</pre> +<p><em>Half-quoted strings</em> are sequences of arbitrary <em>inline characters</em>, +enclosed between half quotation marks. Half quotation marks within the +string <em>must</em> be backslash-escaped, literal backslashes and full quotation +marks <em>may</em> be backslash-escaped (a literal backslash must be escaped if it +occurs before another backslash or immediately before the end of the +string); backslashes before any other characters are left in the string:</p> +<pre class="literal-block"> +HalfQuotedString: "'" (InlineChar - ['\] | "\" InlineChar)* "'"; +</pre> +<p><em>Inline characters</em> are any characters except line separators (CR and LF):</p> +<pre class="literal-block"> +InlineChar: Char - (CR | LF) +</pre> +<p><em>Triple-quoted strings</em> are sequences of arbitrary characters enclosed +between matching triples of full or half quotation marks. They can contain +unescaped newline and quotation characters (as in Python). The string ends +at the first triple of quote characters matching the opening triple, hence +backslash-escaping is still necessary for triples of quote characters of +the appropriate type and for quote characters of the appropriate type +immediately preceding the closing triple. Generally, literal backslashes +and full or half quotation marks may be backslash-escaped, while +backslashes before any other characters are left in the string (as in the +other types of strings):</p> +<pre class="literal-block"> +TripleQuotedString: '"""' Char* '"""' | "'''" Char* "'''"; +</pre> +<p>TODO define other types of atoms (numbers are int or float, use as external +form for basetypes) etc.</p> +<p>literal: "true", "false", and "null".</p> +<p>identifier : (letter | [_@] ) (letter | digit | [_@] ")*</p> +<ul class="simple"> +<li>Atoms: strings, numbers, literals (true, false, null).</li> +</ul> +<p>TODO From the Python grammar:</p> +<dl class="docutils"> +<dt>decimalinteger ::=</dt> +<dd>nonzerodigit digit* | "0"</dd> +<dt>nonzerodigit ::=</dt> +<dd>"1"..."9"</dd> +<dt>floatnumber ::=</dt> +<dd>pointfloat | exponentfloat</dd> +<dt>pointfloat ::=</dt> +<dd>[intpart] fraction | intpart "."</dd> +<dt>exponentfloat ::=</dt> +<dd><dl class="first last docutils"> +<dt>(intpart | pointfloat)</dt> +<dd>exponent</dd> +</dl> +</dd> +<dt>intpart ::=</dt> +<dd>digit+</dd> +<dt>fraction ::=</dt> +<dd>"." digit+</dd> +<dt>exponent ::=</dt> +<dd>("e" | "E") ["+" | "-"] digit+</dd> +</dl> +<p>TODO clean-up rest of document; rename BlockList to block, a document is +probably BlockContent (a block, but without surrounding {}).</p> +<p>A complete DecL <em>document</em> contains a single <em>list</em>:</p> +<pre class="literal-block"> +Document: List; +</pre> +<p>There are two kinds of <em>lists</em>: <em>inline list</em> and <em>block lists</em>:</p> +<pre class="literal-block"> +List: InlineList | BlockList; +</pre> +<p>Each <em>inline list</em> is a series of zero or more <em>simple values</em>:</p> +<pre class="literal-block"> +InlineList: (SimpleValue)*; +</pre> +<p>TODO? Each <em>block list</em> is a series of zero or more <em>block list items</em>:</p> +<pre class="literal-block"> +BlockList: ()*; +</pre> +<p><em>Simple values</em> are <em>atoms</em>, <em>conditions</em>, <em>calculations</em> or <em>inline +lists</em>:</p> +<pre class="literal-block"> +SimpleValue: Atom | Condition | Calculation | InlineList; +</pre> +<p>TODO:</p> +<ul class="simple"> +<li>Identifiers: as in Python, but can also contain the characters "@$." +(also compare with XML identifiers, though ":" and "-" can't be +admitted).</li> +<li>Identifiers can be interpreted as identifier expressions using the "$" +and ".": <em>name$n</em> delivers the n-child of <em>name</em> (list-style access, +probably counting from 0); <em>dictname.childname</em> returns the child(ren) +with the specified <em>childname</em> (hash-style access)--automatically returns +a list if there are several keys with this value. Values are +auto-converted to lists on demand, i.e. <em>dictname.childname$0</em> will work +even if there is only one child with that name. However, this behavior is +application-specific, DecL core doesn't try to interpret identifiers in +any way.</li> +<li>Calculations: evaluate to an atom using standard operators arithmetic +operators (+, -, *, /, %). Can contain Atoms. Grouping is used where +necessary to resolve ambiguities.</li> +<li>Conditions: evaluate to a boolean using standard boolean syntax: logical +connectives (! & | ^), relational operators (== != < > <= >=), set +operators (in ~). Can contain calculations and atoms and atom lists. +Grouping is used where necessary to resolve ambiguities.</li> +</ul> +<p><em>Numbers</em> must satisfy one of the following regular expressions:</p> +<pre class="literal-block"> +[-+]?(0|[1-9][0-9_]*) # base 10 int + [-+]?([0-9][0-9_]*)?\.[0-9.]*([eE][-+][0-9]+)? # base 10 float + [-+]?(inf|Inf) # infinity +(nan|NaN) # not a number +</pre> +<p>Each <em>block list item</em> is a <em>simple item</em> or <em>name/value pair.</em></p> +<p><em>Name/value pairs</em> are either written as a <em>name</em> followed by ":" and +whitespace, followed by a <em>simple value</em>.</p> +<p>TODO <em>Names</em> are <em>simple values</em> or <em>annotated atoms</em>.</p> +</div> +<div class="section" id="type-declaration-language"> +<h2>Type Declaration Language</h2> +<p>TODO describe format used for <tt class="docutils literal"><span class="pre">basetypes.decl</span></tt> (basic types) as well as +for object declarations and complex types. Possibly define additional +<em>optlist</em> field for child categories: <tt class="docutils literal"><span class="pre">parent</span></tt> contains the URI of the +parent category/categories (but in the base types, we just specify the +parent type in parentheses the name)--probably unify name and URI and allow +declaring a <tt class="docutils literal"><span class="pre">@uriprefix</span></tt> field for relative URIs (cf. prefixes used in +N3/RDF). Each file should contain the declaration of an object category as +well as any complex types used in its definition.</p> +</div> +</div> +</body> +</html> diff --git a/doc/formats.rst b/doc/formats.rst new file mode 100644 index 0000000..a1c1a6c --- /dev/null +++ b/doc/formats.rst @@ -0,0 +1,195 @@ +===================== +Formats and Languages +===================== + +The formats and languages used by Tangible Bit are explained in English and +formally defined in EBNF. TODO extract ``::`` blocks and use e.g pyparsing +to autogenerate parsers. + +EBNF Grammar +~~~~~~~~~~~~ + +We use an EBNF notation that is identical to the `EBNF notation used in the +XML specification <http://www.w3.org/TR/xml/#sec-notation>`_, except that +we use ``symbol: expression;`` instead of ``symbol ::= expression`` to +define symbols. + +Predefined Rules +~~~~~~~~~~~~~~~~ + +The following EBNF rules are assumed to be predefined and not formally +defined in this document: + +Char + Any Unicode character + +UnicodeLetter + A character that has the "letter" property in the Unicode database + +CR + a carriage return character (#x0D) + +LF + a line feed character (#x0A) + +Declarations Language (DecL) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A simple, easily writable, readable, and parsable format for declaring +things, used by Tangible Bit for various purposes. + +There are four kinds of *atoms*: *strings*, *numbers*, *identifier +expressions*, and *literals*:: + + Atom: String | Number | IdentifierExpression | Literal; + +There are three types of *strings*: *full-quoted* (enclosed in full +quotation marks), *half-quoted* (enclosed in half quotation marks), and +*triple-quoted* (enclosed in pairs of three matching full or half quotes):: + + String: FullQuotedString | HalfQuotedString | TripleQuotedString; + +*Full-quoted strings* are sequences of arbitrary *inline characters*, +enclosed between full quotation marks. Full quotation marks within the +string *must* be backslash-escaped, literal backslashes and half quotation +marks *may* be backslash-escaped (a literal backslash must be escaped if it +occurs before another backslash or immediately before the end of the +string); backslashes before any other characters are left in the string:: + + FullQuotedString: '"' (InlineChar - ["\] | "\" InlineChar)* '"'; + +*Half-quoted strings* are sequences of arbitrary *inline characters*, +enclosed between half quotation marks. Half quotation marks within the +string *must* be backslash-escaped, literal backslashes and full quotation +marks *may* be backslash-escaped (a literal backslash must be escaped if it +occurs before another backslash or immediately before the end of the +string); backslashes before any other characters are left in the string:: + + HalfQuotedString: "'" (InlineChar - ['\] | "\" InlineChar)* "'"; + +*Inline characters* are any characters except line separators (CR and LF):: + + InlineChar: Char - (CR | LF) + +*Triple-quoted strings* are sequences of arbitrary characters enclosed +between matching triples of full or half quotation marks. They can contain +unescaped newline and quotation characters (as in Python). The string ends +at the first triple of quote characters matching the opening triple, hence +backslash-escaping is still necessary for triples of quote characters of +the appropriate type and for quote characters of the appropriate type +immediately preceding the closing triple. Generally, literal backslashes +and full or half quotation marks may be backslash-escaped, while +backslashes before any other characters are left in the string (as in the +other types of strings):: + + TripleQuotedString: '"""' Char* '"""' | "'''" Char* "'''"; + +TODO define other types of atoms (numbers are int or float, use as external +form for basetypes) etc. + +literal: "true", "false", and "null". + +identifier : (letter | [_@] ) (letter | digit | [_@] ")* + +* Atoms: strings, numbers, literals (true, false, null). + +TODO From the Python grammar: + +decimalinteger ::= + nonzerodigit digit* | "0" + +nonzerodigit ::= + "1"..."9" + +floatnumber ::= + pointfloat | exponentfloat + +pointfloat ::= + [intpart] fraction | intpart "." + +exponentfloat ::= + (intpart | pointfloat) + exponent + +intpart ::= + digit+ + +fraction ::= + "." digit+ + +exponent ::= + ("e" | "E") ["+" | "-"] digit+ + +TODO clean-up rest of document; rename BlockList to block, a document is +probably BlockContent (a block, but without surrounding {}). + +A complete DecL *document* contains a single *list*:: + + Document: List; + +There are two kinds of *lists*: *inline list* and *block lists*:: + + List: InlineList | BlockList; + +Each *inline list* is a series of zero or more *simple values*:: + + InlineList: (SimpleValue)*; + +TODO? Each *block list* is a series of zero or more *block list items*:: + + BlockList: ()*; + +*Simple values* are *atoms*, *conditions*, *calculations* or *inline +lists*:: + + SimpleValue: Atom | Condition | Calculation | InlineList; + + + +TODO: + +* Identifiers: as in Python, but can also contain the characters "@$." + (also compare with XML identifiers, though ":" and "-" can't be + admitted). +* Identifiers can be interpreted as identifier expressions using the "$" + and ".": *name$n* delivers the n-child of *name* (list-style access, + probably counting from 0); *dictname.childname* returns the child(ren) + with the specified *childname* (hash-style access)--automatically returns + a list if there are several keys with this value. Values are + auto-converted to lists on demand, i.e. *dictname.childname$0* will work + even if there is only one child with that name. However, this behavior is + application-specific, DecL core doesn't try to interpret identifiers in + any way. +* Calculations: evaluate to an atom using standard operators arithmetic + operators (+, -, \*, /, %). Can contain Atoms. Grouping is used where + necessary to resolve ambiguities. +* Conditions: evaluate to a boolean using standard boolean syntax: logical + connectives (! & | ^), relational operators (== != < > <= >=), set + operators (in ~). Can contain calculations and atoms and atom lists. + Grouping is used where necessary to resolve ambiguities. + +*Numbers* must satisfy one of the following regular expressions:: + + [-+]?(0|[1-9][0-9_]*) # base 10 int + [-+]?([0-9][0-9_]*)?\.[0-9.]*([eE][-+][0-9]+)? # base 10 float + [-+]?(inf|Inf) # infinity + (nan|NaN) # not a number + +Each *block list item* is a *simple item* or *name/value pair.* + +*Name/value pairs* are either written as a *name* followed by ":" and +whitespace, followed by a *simple value*. + +TODO *Names* are *simple values* or *annotated atoms*. + +Type Declaration Language +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +TODO describe format used for ``basetypes.decl`` (basic types) as well as +for object declarations and complex types. Possibly define additional +*optlist* field for child categories: ``parent`` contains the URI of the +parent category/categories (but in the base types, we just specify the +parent type in parentheses the name)--probably unify name and URI and allow +declaring a ``@uriprefix`` field for relative URIs (cf. prefixes used in +N3/RDF). Each file should contain the declaration of an object category as +well as any complex types used in its definition. diff --git a/doc/objects.html b/doc/objects.html new file mode 100644 index 0000000..b26796d --- /dev/null +++ b/doc/objects.html @@ -0,0 +1,859 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" /> +<title>Tangible Bit Object System</title> +<style type="text/css"> + +/* +:Author: David Goodger (goodger@python.org) +:Id: $Id: html4css1.css 5196 2007-06-03 20:25:28Z wiemann $ +:Copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. + +See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to +customize this style sheet. +*/ + +/* used to remove borders from tables and images */ +.borderless, table.borderless td, table.borderless th { + border: 0 } + +table.borderless td, table.borderless th { + /* Override padding for "table.docutils td" with "! important". + The right padding separates the table cells. */ + padding: 0 0.5em 0 0 ! important } + +.first { + /* Override more specific margin styles with "! important". */ + margin-top: 0 ! important } + +.last, .with-subtitle { + margin-bottom: 0 ! important } + +.hidden { + display: none } + +a.toc-backref { + text-decoration: none ; + color: black } + +blockquote.epigraph { + margin: 2em 5em ; } + +dl.docutils dd { + margin-bottom: 0.5em } + +/* Uncomment (and remove this text!) to get bold-faced definition list terms +dl.docutils dt { + font-weight: bold } +*/ + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.admonition, div.attention, div.caution, div.danger, div.error, +div.hint, div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.admonition p.admonition-title, div.hint p.admonition-title, +div.important p.admonition-title, div.note p.admonition-title, +div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +/* Uncomment (and remove this text!) to get reduced vertical space in + compound paragraphs. +div.compound .compound-first, div.compound .compound-middle { + margin-bottom: 0.5em } + +div.compound .compound-last, div.compound .compound-middle { + margin-top: 0.5em } +*/ + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em ; + margin-right: 2em } + +div.footer, div.header { + clear: both; + font-size: smaller } + +div.line-block { + display: block ; + margin-top: 1em ; + margin-bottom: 1em } + +div.line-block div.line-block { + margin-top: 0 ; + margin-bottom: 0 ; + margin-left: 1.5em } + +div.sidebar { + margin: 0 0 0.5em 1em ; + border: medium outset ; + padding: 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, +h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { + margin-top: 0.4em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr.docutils { + width: 75% } + +img.align-left { + clear: left } + +img.align-right { + clear: right } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.attribution { + text-align: right ; + margin-left: 50% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.rubric { + font-weight: bold ; + font-size: larger ; + color: maroon ; + text-align: center } + +p.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +span.section-subtitle { + /* font-size relative to parent (h1..h6 element) */ + font-size: 80% } + +table.citation { + border-left: solid 1px gray; + margin-left: 1px } + +table.docinfo { + margin: 2em 4em } + +table.docutils { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.footnote { + border-left: solid 1px black; + margin-left: 1px } + +table.docutils td, table.docutils th, +table.docinfo td, table.docinfo th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +table.docutils th.field-name, table.docinfo th.docinfo-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap ; + padding-left: 0 } + +h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, +h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { + font-size: 100% } + +ul.auto-toc { + list-style-type: none } + +</style> +</head> +<body> +<div class="document" id="tangible-bit-object-system"> +<h1 class="title">Tangible Bit Object System</h1> + +<p>The Tangible Bit Object System (TBOS) describes physical objects. It +contains including detailed and automatically processable on how they can +be build, how they can be used, and what they can be used for. The TBOS +takes care of the entire life cycle of an object, including information on +maintenance, part replacement, and repair, and disassembly.</p> +<p>Each object has <em>properties</em> that describe the object. Each object is +associated with <em>processes</em> that describe how the object can be build, +used, maintained, repaired, modified, or dismantled.</p> +<div class="section" id="object-descriptions"> +<h2>Object Descriptions</h2> +<p>The most important property of each object are its <em>categories</em> (types). +This allows placing all objects in a type hierarchy. Each category extends +another category, the most general object category is <em>Object</em>; each object +is an instance of one or several category (we allow multiple inheritance +here). The hierarchy of object categories, as known to Tangible Bit, is +stored in <tt class="docutils literal"><span class="pre">doc/object_categories.txt</span></tt> (TODO should be formalized and +moved outside the <tt class="docutils literal"><span class="pre">doc</span></tt> directory; it should be possible to just refer to +categories by URI to remove the dependency on a single authority). The +object category also specified which other properties the object has.</p> +<p>The properties of the <em>Object</em> category, which are shared by all objects, +are as follows:</p> +<pre class="literal-block"> +Object { + uri: "http://tangiblebit.com/cat/object"; + desc: "The root of the object hierarchy"; + + # Required properties + req { + name(freetext): "An informal name of the object."; + + uri(string): + """An URI uniquely identifying the object; it's a good idea (but not + required) to use a HTTP URI and set up a web page at the specified + location, where interested users can find information on the object + and download it. Sample: http://example.com/design/coffeemaker if you + own the example.com domain."""; + + summary(freetext): + """A short (one line) description of what the object is and what it + can be used for."""; + + license(string): + """The license under which the object is made available (must be + compatible with CC-SA-BY or a free software/open source license in + order to allow inclusion in the TB object database). On the TBit + website there is controlled vocabulary of license names that should + be used in this field and in the *softwareLicense* field."""; + } + + # Optional properties + opt { + description(formattedtext): + "A longer description of the object."; + + lastModified(timestamp): + """Timestamp showing when the object metadata or the files or + processes connected with the object where last modified."""; + + weight(mass): + "The weight of the object (set to 0 if this is a non-material object)."; + + width(length): + """The total width of the object, when fitting it into a box (0 if + this is a non-material object)."""; + + depth(length): + """The total depth of the object, when fitting it into a box (0 if + this is a non-material object)."""; + + height(length): + """The total height of the object, when fitting it into a box (0 if + this is a non-material object)."""; + + softwareLicense(string): + """The license under which the software related to the object is made + available (must be compatible with CC-SA-BY or a free software/open + source license in order to allow inclusion in the TB object + database). If omitted, the value given in the *license* field is used + instead."""; + } + + # Properties occurring once or more + reqlist { + category(identifier): "List of categories the object belongs to."; + + author(string): "List of the people which created/packaged the object."; + + maintainer(string): + "List of people to contact regarding questions about the object."; + + replaces(string): + "List of object URIs this object is meant to replace/make obsolete"; + } + + # Properties occurring any number of times + optlist { + thumbnail(File): + """A list of small visual depictions of the object (pointers to image + files)."""; + + file(File): "List of files associated with the object."; + + process(Process): "List of processes associated with the object."; + } + + +# The complex types used in Object declarations + +File { + + req { # Required + role(string): + """The role of the file in regard to the object, e.g. "depiction" + (audio/visual of the object, e.g. a photo, drawing, or movie), "faq", + "whitepaper". On the TBit website there is controlled vocabulary of + recommended values for this field. Note: files such as "manual" + shouldn't be stored here; rather, they should be associated with a + *use process* (cf. below)."""; + + name(string): "The name of the file."; + + mimetype(string): "The MIME type."; + } + + opt { # Optional + description(freetext): + "A (preferably short) description of the file and its purpose"; + } +} + +Process { + req { # Required + role(string): + """The role of the process in regard to the object, one of + + * build: how to build/produce the object. + * setup: how to setup the object prior to using it (comes between + build and usage, and can optionally later be repeated when + necessary.) Sample: program channel list on a TV set. + * use: how to use the object, in general or for some specific + purpose. + * dismantle: how to dismantle/disassemble the object. + * maintain: how to maintain the object--describes operations that + need to be performed regularly or occasionally to keep the object + in good order. Sample: change oil in a car. + * repair: how to repair the object or some parts of it. + * replace: how to replace same part of the object."""; + + process(string): "The URI of the process."; + + software(bool): + """If true, this file is licensed under the conditions specified in + the *softwareLicense* field, otherwise under the conditions of the + *license* field. This field is only used to provide licensing + information (it does not matter whether the file really contains + software)."""; + + description(freetext): + """A (preferably short) description of the process in relation to the + object."""; + + } +} + +</pre> +<p>TODO include parsed and beautified version of that file instead of its raw +source.</p> +<p>Samples of additional properties that could be defined for a VisualDisplay:</p> +<ul class="simple"> +<li>resolutionX (int)</li> +<li>resolutionY (int)</li> +<li>displayWidth (length)</li> +<li>displayHeight (length)</li> +</ul> +<p>New object categories can be declared by defining a name and an URI for the +category and by specifying the URI of a parent category (<em>Object</em> or a +category derived from it) and a list of additional properties supported by +the new category. Category declarations are given in the Type Declaration +Language, cf. <tt class="docutils literal"><span class="pre">formats</span></tt>.</p> +<p>The following basic types can be used for additional properties:</p> +<pre class="literal-block"> +# The basic types that can be used for atomic fields. Types not defined +# here are complex types, made up of several atomic or complex types. + +int: "An integer number. External form: as in JSON."; + +float: "A floating point number. External form: as in JSON."; + +bool: 'A Boolean value, either "true" or "false".'; + +string: + """A string. Use this base type for free-form strings that are not meant + to be localized. Strings can contain arbitrary Unicode characters."""; + +timestamp: + """A point in time. External form: like the `YAML timestamp + <http://yaml.org/type/timestamp.html>`_ type."""; + +identifier(string): + "An identifier, made up of alphanumeric characters and underscores."; + +freetext(string): + "Text that can be localized (translated in other languages)."; + +formattedtext(freetext): + "A longer block of text that can contain formatting."; + +file(string): "A pointer to a file (stored externally)."; + +# Unit types + +length(float): "A length, measured by default in meter (m)."; + +mass(float): "A mass, measured by default in kilogram (kg)."; + +</pre> +<p>TODO include parsed and beautified version of that file instead of its raw +source.</p> +<p>All properties that require a unit come with a "natural unit" taken, when +possible, from the <a class="reference external" href="http://en.wikipedia.org/wiki/International_System_of_Units">International System of Units</a> (meter, +kilogram, second, ampere, degree Celsius, candela, joule, watt, volt, +hertz, ohm, lumen etc.). Thus units need never be stored in the DB. The +obvious exception is money, where a unit (e.g. USD or EUR) must be +supplied.</p> +<p>Additional properties can also be <em>complex types</em>, made up of several +atomic or complex types. Examples of complex types are the <em>file</em> and +<em>process</em> properties of the <em>Object</em> type. Complex types are declared in +the same way as object categories (cf. <tt class="docutils literal"><span class="pre">formats</span></tt>).</p> +</div> +<div class="section" id="process-descriptions"> +<h2>Process Descriptions</h2> +<p>Processes describe the life cycle of an object: how it and be built; how it +can be used and what it can be used for; how it can be maintained, +repaired, and modified; and how it can be dismantled and discarded or +recycled when it has reached the end of its life cycle. Without processes, +any object would be pretty useless.</p> +<p>Each process description has the following elements:</p> +<div class="section" id="metadata"> +<h3>Metadata</h3> +<ul class="simple"> +<li><em>name:</em> an informal name and short summary of the process</li> +<li><em>id:</em> a DI uniquely identifying the process. Tip: derive from the URI +of the corresponding object (e.g. +<tt class="docutils literal"><span class="pre">com.example.coffeemaker.buildit</span></tt> for the coffeemaker example above)</li> +<li><em>description:</em> a description of the process</li> +<li><em>authors:</em> list of the people which created/packaged the process +(typically same as for the corresponding object)</li> +<li><em>maintainers:</em> list of people to contact regarding questions about the +process (typically same as for the corresponding object)</li> +<li><em>last-modified:</em> timestamp showing when the process was last modified</li> +<li><em>license:</em> the license under which the process is made available +(typically same as for the corresponding object)</li> +<li><em>files:</em> list of files associated with the process (same format as above)</li> +</ul> +</div> +<div class="section" id="input"> +<h3>Input</h3> +<p>Lists materials and components that are required for the process; including +the amount or the number of instances required. Materials and objects +listed here are used up or transformed during the process.</p> +<p>Input requirements are probably listed using the TB query language, which +might look like this:</p> +<pre class="literal-block"> +object ? (type ~ SheetMetal & material = Aluminum & width = 1.5 & + depth = 0.3 height = 0.003 & copies = 12); +material ? (type ~ ABS & amount = 0.5); +</pre> +<p>(12 sheets made from aluminum or steel, size 150x30 cm, height between 3 +and 4 mm; and 0.5 kg of ABS plastic.)</p> +<p>A name can be declared before the "?", e.g. <tt class="docutils literal"><span class="pre">material</span> <span class="pre">"MyMaterial"</span> <span class="pre">?</span></tt>. +The name used for referring to the object/material later in scripting, +otherwise the category (e.g. "SheetMetal" or "ABS") is used.</p> +<p>The <a class="reference external" href="http://code.gustavonarea.net/booleano/">Booleano</a>-based query +syntax is straightforward:</p> +<ul class="simple"> +<li>Logical operators:<ul> +<li>and: &</li> +<li>or: |</li> +<li>not: !</li> +</ul> +</li> +<li>Comparison operators:<ul> +<li>Equal: = (or maybe ==)</li> +<li>Not equal: !=</li> +<li>Less/greater [or equal] than: < > <= >=</li> +<li>"Similarity": ~ . <tt class="docutils literal"><span class="pre">A</span> <span class="pre">~</span> <span class="pre">B</span></tt> means:<ul> +<li>A is a subcategory of B, if A and B are categories</li> +<li>A contains B as a substring (case-insensitive), if A and B are +strings (similar to SQL LIKE)</li> +<li>Maybe: abs(A-B) < 0.01, if A and B are numbers (rough equality +check)</li> +<li>Undefined (error) otherwise</li> +</ul> +</li> +</ul> +</li> +<li>Items are separated using <tt class="docutils literal"><span class="pre">;</span></tt> or <tt class="docutils literal"><span class="pre">&</span></tt>, indicating that both are +required; or using <tt class="docutils literal"><span class="pre">|</span></tt> indicating that one of the is required.</li> +</ul> +<p>Additional properties, not defined by the object category:</p> +<ul class="simple"> +<li>copies (int): the number of instances required, for discrete items. +Default is 1.</li> +<li>amount (mass): the amount (in kilogram) required, for non-discrete items. +No default value. Only one of <em>copies</em> or <em>amount</em> may be specified, but +not both.</li> +</ul> +<p>The input requirements are often called "bill of materials (BOM)", but they +can contain materials <em>and</em> objects.</p> +</div> +<div class="section" id="tools"> +<h3>Tools</h3> +<p>Lists tools and resources that are used in the process, but that aren't +used up. Tools are listed in the same way as inputs, e.g.:</p> +<pre class="literal-block"> +object ? (category ~ WaterHeater & achievableHeat >= 100 + & heatableVolume >= 2); +</pre> +<p>(A water heater than can heat 2 liters of water (or more) to 100 degree +Celsius (or more), required for ca. 15 minutes.)</p> +<p>Additional property:</p> +<ul class="simple"> +<li>time (time?): an estimate of the time for which the tool is +required--useful e.g. for cost calculations if a tool is shared or rented +on a temporal basis.</li> +</ul> +</div> +<div class="section" id="constraints"> +<h3>Constraints</h3> +<p>Lists conditions that must be true for the process to be performed as +expected. Described in the same way as inputs, e.g.:</p> +<pre class="literal-block"> +constraint ? (10 <= EnvironmentTemperature <= 35) +</pre> +<p>(The environmental temperature must be between 10 and 35 °C.)</p> +<p>TODO Maybe, instead of constraints, define "location requirements", making +this a property of the location (the place where the process will be +performed)?</p> +<p>Implementation note: input, tools, and constraints can be stored as "saved +queries" in the database.</p> +</div> +<div class="section" id="output"> +<h3>Output</h3> +<p>The output describes the objects that will be created as a result of the +process, if any. Output is specified in a simple declarative language, +maybe (similar to the Kokompe language, but using ":" instead of ":="):</p> +<pre class="literal-block"> +object { + category: WaterBoiler; + achievableHeat: [60, 80, 90, 100]; # a list + heatableVolume: [0..3]; # a range + power: 700; + weight: 2.8; + width: 0.28; + depth: 0.2; + height: 0.29; +} +</pre> +<p>(A water boiler that can heat up to 3 liters of water to 60, 80, 90, or 100 +°C, needs 700 W, weights 2.8 kg etc.)</p> +<p>For processes that don't <em>create</em> any objects, but only repair, maintain, +or use them, no output will be defined. Processes that dismantle objects +should list the resulting remains or waste as output.</p> +</div> +<div class="section" id="operations"> +<h3>Operations</h3> +<p>This is the core of the process: the list of operations to be performed as +part of the process. Operations are partially ordered: some must be +performed sequentially, others can be performed simultaneously or in +arbitrary order.</p> +<p>For each operation, there is an <em>agent</em> that should realize the +operation--either one of the <em>tools</em> required for the process (or, in some +cases, one of the <em>inputs</em> defined?), or a human.</p> +<p>Operations will ofter refer to one <em>files</em> attached to the process: CNC +router should execute the toolpath defined in file X, human should bolt the +components together as shown in PDF file Y, etc.</p> +<p>By default, operations are <em>sequential</em>, they must be executed in the +defined order; alternatively, groups of operations can be marked as +<em>parallel</em> which allows them to be executed in parallel or in arbitrary +order. Groups of operations can also be <em>alternative</em> (do this or do that); +they can also be <em>conditional</em> (if...then...else). Groups of operations can +be <em>repeated</em> (while... block) for a certain number of times or until a +certain condition is true.</p> +<p>Here's an example of how the different kinds of grouping constructs could +look like, using a simple block-based syntax and placeholders instead of +actual operations:</p> +<pre class="literal-block"> +parallel: # execute these operations in any order + Bla + Bla + Bla + +sequential: # You can use this inside a parallel block. Otherwise you + # won't need it, as all other blocks are sequential by + # default. + Bla + Bla + Bla + +alternative: # select one of those processes + Bla + Bla + Bla + +if *condition*: + Bla + Bla + Bla +elif *another-condition*: +else + Blub + +while *condition*: + Bla + Bla + Bla + +for i in [10..1], i + 1: # repeat 10 times (increasing the value of i) + Bla + Bla + Bla + +# The argument of a for loop is a list... +for file in [fileA, fileB, fileC]: # do this for each of the 3 files + Bla + Bla + +# ...or a range... +for i in [1..10]: # repeat 10 times (increasing the value of i) + Bla + Bla + +# ...with an optional step argument +for i in [10..1] step -1: # repeat 10 times, counting downwards + Bla + Bla +</pre> +<p>The words "parallel", "sequential", "alternative", "if", "elif", "else", +"while", "for", "in" are reserved keywords. "step" is not reserved as it +can only be used after a range in a for loop, where variable names are not +allowed, so there is no risk of confusion.</p> +<p>TODO Describe how operations targeted at a human or at an object could be +defined; how to define <em>conditions</em> either for automatic evaluation or as +queries to a human.</p> +</div> +<div class="section" id="parameters"> +<h3>Parameters</h3> +<p>It should be possible for process to accept <em>parameters</em> that influence the +process--for example, if you built a chair, you can configure the exact +length of the legs, specify whether it should have a cushion, select the +color etc.</p> +<p>For each parameter, the supported range or enumeration of values should be +predefined; the user then chooses among the available options.</p> +<p>The choice of parameter values can influence the other elements of the +process--exact input requirements and output specification will depend on +them; some of the operations will change to reflect to them; possibly, the +tools required will change too.</p> +<p>When storing options in the DB, the whole range or enum should be stored in +order to be searchable (e.g. a chair that can be made in any color with +legs between 35 cm and 80 cm should match a search for a red chair with 50 +cm legs.) That's more difficult for input/tool requirements, however (we +can calculate and store how much material a 35 cm or a 80 cm chair would +need, but we can't precalculate and store such information for <em>all</em> +possible values). A possible, though imperfect solution would be to store +such information for the <em>minimum</em> and <em>maximum</em> values of numeric +parameters, and for a <em>default</em> value for enum parameters; and to calculate +the exact values on demand.</p> +<p>Example of declaring parameters:</p> +<pre class="literal-block"> +# leg length is between 35 cm and 80 cm +leg-length: [0.35..0.80]; +# six different colors are available +color: [red, green, blue, yellow, black, white]; +</pre> +<p>Example of selecting parameters--syntax is identical to the syntax used for +defining inputs:</p> +<pre class="literal-block"> +# we want a blue chair with 50 cm legs +leg-length = 0.5 & color = "blue"; +</pre> +</div> +</div> +<div class="section" id="object-database"> +<h2>Object Database</h2> +<p>TODO Describe how objects and processes are stored in the DB.</p> +</div> +<div class="section" id="tangible-bit-object-description"> +<h2>Tangible Bit Object Description</h2> +<p>The <em>Tangible Bit Object</em> file format (extension: <em>.tbob</em>) allows +extracting objects with their relevant processes from the database and +sharing them computers and users. A TBOB file can contain one or many +objects with their relevant processes.</p> +<p>A TBOB package is a ZIP file (like formats such as ODT and EPUB).</p> +<p>First-level directories: the file contains one directory for objects and +one for each type of processes it contains:</p> +<pre class="literal-block"> +objects +build +setup +use +maintain +repair +replace +</pre> +<p>(Empty directories can be omitted.)</p> +<p>Second-level directories: Each object and each process is stored in a +subdirectory of the corresponding folder, using the object/process ID as +directory name (e.g. <tt class="docutils literal"><span class="pre">objects/com.example.coffeemaker</span></tt>).</p> +<p>TODO reverted from IDs to URIs since that's more user-friendly (allowing a +web page to be shown). Explain how to convert URIs to directory names.</p> +<p>Each object is represented by 3 simple plaintext (OGDL?) files:</p> +<ul class="simple"> +<li>properties.og: contains the object properties</li> +<li>processes.og: index of processes associated with the object</li> +<li>files.og: index of files associated with the object</li> +</ul> +<p>Each process is represented by 5 simple plaintext (OGDL?) files:</p> +<ul class="simple"> +<li>properties.og: contains the process metadata</li> +<li>dependencies.og: lists the input, tools, and constraints required</li> +<li>result.og: defines the output and the allowed parameter settings</li> +<li>operations.og: defines the list of operations to be performed</li> +<li>files.og: index of files associated with the process</li> +</ul> +<p>If an object or process contains files, they are stored in a third-level +folder named <tt class="docutils literal"><span class="pre">files</span></tt>.</p> +<p>TODO mimetype file?; internationalization/translated strings?</p> +<p>Sample directory structure:</p> +<pre class="literal-block"> +objects/ + com.example.coffeemaker/ + properties.og + processes.og + files.og + files/ + thumbnail.gif + frontview.jpg +build/ + com.example.coffeemaker.buildit/ + properties.og + dependencies.og + result.og + operations.og + files.og + files/ + blueprint.iges +</pre> +<p>TODO Ensure that it's OK to package GPL'ed software with non-GPL'ed content +in a single ZIP file (should be).</p> +</div> +<div class="section" id="to-do"> +<h2>To Do</h2> +<ul class="simple"> +<li>Decide on syntax to use in <em>formattedtext</em> (Markdown or WikiCreole?).</li> +<li>Write sample object package (Drawdio?) and tutorial/overview document on +documenting and packing objects.</li> +<li>Get in dialog with people creating and using free designs about what they +need and whether our approach suits them.</li> +<li>Document format of declarations (DecL language) and write parser; define +literal form / parse expression of the <em>basetypes</em>.</li> +<li>Write database generator that reads the type declarations and creates or +updates the database scheme accordingly.</li> +<li>Define and publish controlled vocabulary of recommended license names and +of the roles of files.</li> +<li>See TODOs above.</li> +</ul> +</div> +</div> +</body> +</html> diff --git a/doc/objects.rst b/doc/objects.rst new file mode 100644 index 0000000..36042d2 --- /dev/null +++ b/doc/objects.rst @@ -0,0 +1,435 @@ +========================== +Tangible Bit Object System +========================== + +The Tangible Bit Object System (TBOS) describes physical objects. It +contains including detailed and automatically processable on how they can +be build, how they can be used, and what they can be used for. The TBOS +takes care of the entire life cycle of an object, including information on +maintenance, part replacement, and repair, and disassembly. + +Each object has *properties* that describe the object. Each object is +associated with *processes* that describe how the object can be build, +used, maintained, repaired, modified, or dismantled. + +Object Descriptions +~~~~~~~~~~~~~~~~~~~ + +The most important property of each object are its *categories* (types). +This allows placing all objects in a type hierarchy. Each category extends +another category, the most general object category is *Object*; each object +is an instance of one or several category (we allow multiple inheritance +here). The hierarchy of object categories, as known to Tangible Bit, is +stored in ``doc/object_categories.txt`` (TODO should be formalized and +moved outside the ``doc`` directory; it should be possible to just refer to +categories by URI to remove the dependency on a single authority). The +object category also specified which other properties the object has. + +The properties of the *Object* category, which are shared by all objects, +are as follows: + +.. include:: ../data/types/object.decl + :literal: + +TODO include parsed and beautified version of that file instead of its raw +source. + +Samples of additional properties that could be defined for a VisualDisplay: + +- resolutionX (int) +- resolutionY (int) +- displayWidth (length) +- displayHeight (length) + +New object categories can be declared by defining a name and an URI for the +category and by specifying the URI of a parent category (*Object* or a +category derived from it) and a list of additional properties supported by +the new category. Category declarations are given in the Type Declaration +Language, cf. ``formats``. + +The following basic types can be used for additional properties: + +.. include:: ../data/types/basetypes.decl + :literal: + +TODO include parsed and beautified version of that file instead of its raw +source. + +All properties that require a unit come with a "natural unit" taken, when +possible, from the `International System of Units +<http://en.wikipedia.org/wiki/International_System_of_Units>`_ (meter, +kilogram, second, ampere, degree Celsius, candela, joule, watt, volt, +hertz, ohm, lumen etc.). Thus units need never be stored in the DB. The +obvious exception is money, where a unit (e.g. USD or EUR) must be +supplied. + +Additional properties can also be *complex types*, made up of several +atomic or complex types. Examples of complex types are the *file* and +*process* properties of the *Object* type. Complex types are declared in +the same way as object categories (cf. ``formats``). + +Process Descriptions +~~~~~~~~~~~~~~~~~~~~ + +Processes describe the life cycle of an object: how it and be built; how it +can be used and what it can be used for; how it can be maintained, +repaired, and modified; and how it can be dismantled and discarded or +recycled when it has reached the end of its life cycle. Without processes, +any object would be pretty useless. + +Each process description has the following elements: + +Metadata +++++++++ + +* *name:* an informal name and short summary of the process +* *id:* a DI uniquely identifying the process. Tip: derive from the URI + of the corresponding object (e.g. + ``com.example.coffeemaker.buildit`` for the coffeemaker example above) +* *description:* a description of the process +* *authors:* list of the people which created/packaged the process + (typically same as for the corresponding object) +* *maintainers:* list of people to contact regarding questions about the + process (typically same as for the corresponding object) +* *last-modified:* timestamp showing when the process was last modified +* *license:* the license under which the process is made available + (typically same as for the corresponding object) +* *files:* list of files associated with the process (same format as above) + +Input ++++++ + +Lists materials and components that are required for the process; including +the amount or the number of instances required. Materials and objects +listed here are used up or transformed during the process. + +Input requirements are probably listed using the TB query language, which +might look like this:: + + object ? (type ~ SheetMetal & material = Aluminum & width = 1.5 & + depth = 0.3 height = 0.003 & copies = 12); + material ? (type ~ ABS & amount = 0.5); + +(12 sheets made from aluminum or steel, size 150x30 cm, height between 3 +and 4 mm; and 0.5 kg of ABS plastic.) + +A name can be declared before the "?", e.g. ``material "MyMaterial" ?``. +The name used for referring to the object/material later in scripting, +otherwise the category (e.g. "SheetMetal" or "ABS") is used. + +The `Booleano <http://code.gustavonarea.net/booleano/>`_\ -based query +syntax is straightforward: + +* Logical operators: + + * and: & + * or: | + * not: ! + +* Comparison operators: + + * Equal: = (or maybe ==) + * Not equal: != + * Less/greater [or equal] than: < > <= >= + * "Similarity": ~ . ``A ~ B`` means: + + * A is a subcategory of B, if A and B are categories + * A contains B as a substring (case-insensitive), if A and B are + strings (similar to SQL LIKE) + * Maybe: abs(A-B) < 0.01, if A and B are numbers (rough equality + check) + * Undefined (error) otherwise + +* Items are separated using ``;`` or ``&``, indicating that both are + required; or using ``|`` indicating that one of the is required. + +Additional properties, not defined by the object category: + +* copies (int): the number of instances required, for discrete items. + Default is 1. +* amount (mass): the amount (in kilogram) required, for non-discrete items. + No default value. Only one of *copies* or *amount* may be specified, but + not both. + +The input requirements are often called "bill of materials (BOM)", but they +can contain materials *and* objects. + +Tools ++++++ + +Lists tools and resources that are used in the process, but that aren't +used up. Tools are listed in the same way as inputs, e.g.:: + + object ? (category ~ WaterHeater & achievableHeat >= 100 + & heatableVolume >= 2); + +(A water heater than can heat 2 liters of water (or more) to 100 degree +Celsius (or more), required for ca. 15 minutes.) + +Additional property: + +* time (time?): an estimate of the time for which the tool is + required--useful e.g. for cost calculations if a tool is shared or rented + on a temporal basis. + +Constraints ++++++++++++ + +Lists conditions that must be true for the process to be performed as +expected. Described in the same way as inputs, e.g.:: + + constraint ? (10 <= EnvironmentTemperature <= 35) + +(The environmental temperature must be between 10 and 35 °C.) + +TODO Maybe, instead of constraints, define "location requirements", making +this a property of the location (the place where the process will be +performed)? + +Implementation note: input, tools, and constraints can be stored as "saved +queries" in the database. + +Output +++++++ + +The output describes the objects that will be created as a result of the +process, if any. Output is specified in a simple declarative language, +maybe (similar to the Kokompe language, but using ":" instead of ":="):: + + object { + category: WaterBoiler; + achievableHeat: [60, 80, 90, 100]; # a list + heatableVolume: [0..3]; # a range + power: 700; + weight: 2.8; + width: 0.28; + depth: 0.2; + height: 0.29; + } + +(A water boiler that can heat up to 3 liters of water to 60, 80, 90, or 100 +°C, needs 700 W, weights 2.8 kg etc.) + +For processes that don't *create* any objects, but only repair, maintain, +or use them, no output will be defined. Processes that dismantle objects +should list the resulting remains or waste as output. + +Operations +++++++++++ + +This is the core of the process: the list of operations to be performed as +part of the process. Operations are partially ordered: some must be +performed sequentially, others can be performed simultaneously or in +arbitrary order. + +For each operation, there is an *agent* that should realize the +operation--either one of the *tools* required for the process (or, in some +cases, one of the *inputs* defined?), or a human. + +Operations will ofter refer to one *files* attached to the process: CNC +router should execute the toolpath defined in file X, human should bolt the +components together as shown in PDF file Y, etc. + +By default, operations are *sequential*, they must be executed in the +defined order; alternatively, groups of operations can be marked as +*parallel* which allows them to be executed in parallel or in arbitrary +order. Groups of operations can also be *alternative* (do this or do that); +they can also be *conditional* (if...then...else). Groups of operations can +be *repeated* (while... block) for a certain number of times or until a +certain condition is true. + +Here's an example of how the different kinds of grouping constructs could +look like, using a simple block-based syntax and placeholders instead of +actual operations:: + + parallel: # execute these operations in any order + Bla + Bla + Bla + + sequential: # You can use this inside a parallel block. Otherwise you + # won't need it, as all other blocks are sequential by + # default. + Bla + Bla + Bla + + alternative: # select one of those processes + Bla + Bla + Bla + + if *condition*: + Bla + Bla + Bla + elif *another-condition*: + else + Blub + + while *condition*: + Bla + Bla + Bla + + for i in [10..1], i + 1: # repeat 10 times (increasing the value of i) + Bla + Bla + Bla + + # The argument of a for loop is a list... + for file in [fileA, fileB, fileC]: # do this for each of the 3 files + Bla + Bla + + # ...or a range... + for i in [1..10]: # repeat 10 times (increasing the value of i) + Bla + Bla + + # ...with an optional step argument + for i in [10..1] step -1: # repeat 10 times, counting downwards + Bla + Bla + +The words "parallel", "sequential", "alternative", "if", "elif", "else", +"while", "for", "in" are reserved keywords. "step" is not reserved as it +can only be used after a range in a for loop, where variable names are not +allowed, so there is no risk of confusion. + +TODO Describe how operations targeted at a human or at an object could be +defined; how to define *conditions* either for automatic evaluation or as +queries to a human. + +Parameters +++++++++++ + +It should be possible for process to accept *parameters* that influence the +process--for example, if you built a chair, you can configure the exact +length of the legs, specify whether it should have a cushion, select the +color etc. + +For each parameter, the supported range or enumeration of values should be +predefined; the user then chooses among the available options. + +The choice of parameter values can influence the other elements of the +process--exact input requirements and output specification will depend on +them; some of the operations will change to reflect to them; possibly, the +tools required will change too. + +When storing options in the DB, the whole range or enum should be stored in +order to be searchable (e.g. a chair that can be made in any color with +legs between 35 cm and 80 cm should match a search for a red chair with 50 +cm legs.) That's more difficult for input/tool requirements, however (we +can calculate and store how much material a 35 cm or a 80 cm chair would +need, but we can't precalculate and store such information for *all* +possible values). A possible, though imperfect solution would be to store +such information for the *minimum* and *maximum* values of numeric +parameters, and for a *default* value for enum parameters; and to calculate +the exact values on demand. + +Example of declaring parameters:: + + # leg length is between 35 cm and 80 cm + leg-length: [0.35..0.80]; + # six different colors are available + color: [red, green, blue, yellow, black, white]; + +Example of selecting parameters--syntax is identical to the syntax used for +defining inputs:: + + # we want a blue chair with 50 cm legs + leg-length = 0.5 & color = "blue"; + +Object Database +~~~~~~~~~~~~~~~ + +TODO Describe how objects and processes are stored in the DB. + +Tangible Bit Object Description +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The *Tangible Bit Object* file format (extension: *.tbob*) allows +extracting objects with their relevant processes from the database and +sharing them computers and users. A TBOB file can contain one or many +objects with their relevant processes. + +A TBOB package is a ZIP file (like formats such as ODT and EPUB). + +First-level directories: the file contains one directory for objects and +one for each type of processes it contains:: + + objects + build + setup + use + maintain + repair + replace + +(Empty directories can be omitted.) + +Second-level directories: Each object and each process is stored in a +subdirectory of the corresponding folder, using the object/process ID as +directory name (e.g. ``objects/com.example.coffeemaker``). + +TODO reverted from IDs to URIs since that's more user-friendly (allowing a +web page to be shown). Explain how to convert URIs to directory names. + +Each object is represented by 3 simple plaintext (OGDL?) files: + +- properties.og: contains the object properties +- processes.og: index of processes associated with the object +- files.og: index of files associated with the object + +Each process is represented by 5 simple plaintext (OGDL?) files: + +- properties.og: contains the process metadata +- dependencies.og: lists the input, tools, and constraints required +- result.og: defines the output and the allowed parameter settings +- operations.og: defines the list of operations to be performed +- files.og: index of files associated with the process + +If an object or process contains files, they are stored in a third-level +folder named ``files``. + +TODO mimetype file?; internationalization/translated strings? + +Sample directory structure:: + + objects/ + com.example.coffeemaker/ + properties.og + processes.og + files.og + files/ + thumbnail.gif + frontview.jpg + build/ + com.example.coffeemaker.buildit/ + properties.og + dependencies.og + result.og + operations.og + files.og + files/ + blueprint.iges + +TODO Ensure that it's OK to package GPL'ed software with non-GPL'ed content +in a single ZIP file (should be). + +To Do +~~~~~ + +* Decide on syntax to use in *formattedtext* (Markdown or WikiCreole?). +* Write sample object package (Drawdio?) and tutorial/overview document on + documenting and packing objects. +* Get in dialog with people creating and using free designs about what they + need and whether our approach suits them. +* Document format of declarations (DecL language) and write parser; define + literal form / parse expression of the *basetypes*. +* Write database generator that reads the type declarations and creates or + updates the database scheme accordingly. +* Define and publish controlled vocabulary of recommended license names and + of the roles of files. +* See TODOs above. @@ -147,6 +147,10 @@ Current database layout: Here we need input regarding the design, structure, and contents of the materials science database. +Object System +~~~~~~~~~~~~~ + +See ``objects.rst``. Industrial Capacity Mapping ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -163,4 +167,12 @@ Inventory Manager Inventory Management tool info. +Formats and Languages +~~~~~~~~~~~~~~~~~~~~~ + +See ``formats.rst``. + +Coding Style & Development Notes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +See ``dev.rst``. diff --git a/server/locations/views.py b/server/locations/views.py index 7f5e730..f509c7a 100644 --- a/server/locations/views.py +++ b/server/locations/views.py @@ -4,6 +4,7 @@ from locations.models import * from locations.xmlrpc import * from django.http import HttpResponse from django.contrib.auth.models import User +from django.db.models import Q import simplejson import time @@ -22,10 +23,30 @@ def search(request): query = request.GET['q'] if not query or query == "": - return HttpResonse(simplejson.encode(GetLocationList())) + return HttpResponse(simplejson.encode(GetLocationList())) else: - # FIXME: This isn't actually a real search function at the moment. - return HttpResonse(simplejson.encode(GetLocationList())) + q = Q() + for qs in query.split(" "): + q &= Q(name__contains=qs) | Q(locname__contains=qs) + + try: + locations = Location.objects.get(q) + except: + return HttpResponse("[]") + + results = [] + + for location in locations: + results.append({ + 'id': location.id, + 'lat': location.lat, + 'lon': location.lon, + 'name': location.name, + 'city': location.locname, + 'website': location.website + }) + + return HttpResponse(simplejson.encode(results)) def setlocation(request): if not request.has_key('locationid'): diff --git a/server/locations/xmlrpc.py b/server/locations/xmlrpc.py index c2ec2f2..5d22bdf 100644 --- a/server/locations/xmlrpc.py +++ b/server/locations/xmlrpc.py @@ -12,7 +12,14 @@ def GetLocationList(): results = [] for location in locations: - results.append({ 'id': location.id, 'lat': location.lat, 'lon': location.lon, 'name': location.name, 'locname': location.locname, 'weblocation': location.website}) + results.append({ + 'id': location.id, + 'lat': location.lat, + 'lon': location.lon, + 'name': location.name, + 'locname': location.locname, + 'website': location.website + }) return results diff --git a/server/objects/models.py b/server/objects/models.py index fdb0062..a9471a3 100644 --- a/server/objects/models.py +++ b/server/objects/models.py @@ -25,6 +25,13 @@ class Object(models.Model): files = models.ManyToManyField(ObjectFile) +class Product(models.Model): + # To map product codes (EAN, UPC,...) to objects. + code = models.CharField(max_length=18, primary_key=True) + name = models.CharField(max_length=200) + object = models.ForeignKey(Object, blank=True, null=True) + + class Intangible(models.Model): # TODO: Define me! # Heat, pressure, electricity, manpower,... @@ -40,4 +47,5 @@ class ObjectSearchForm(ModelForm): model = Object + admin.site.register(Object) diff --git a/server/objects/views.py b/server/objects/views.py index 524ba08..cdf45d3 100644 --- a/server/objects/views.py +++ b/server/objects/views.py @@ -1,8 +1,27 @@ +from django.http import HttpResponse from django.shortcuts import render_to_response from objects.models import * +import simplejson def index(request): objsearchform = ObjectSearchForm(auto_id="catalogsearch") return render_to_response("objects/index.html", {"catalogsearch": objsearchform, "user": request.user}) +def ean_lookup(request): + query = request.GET["q"].split(",") + + try: + results = Product.objects.filter(code__in=query) + products = [] + + for r in results: + products.append({ + 'code': r.code, + 'name': r.name + }) + + return HttpResponse(simplejson.encode(products)) + except Exception as e: + print e + return HttpResponse("[]") diff --git a/server/urls.py b/server/urls.py index 375b0fa..ab694ab 100644 --- a/server/urls.py +++ b/server/urls.py @@ -32,6 +32,7 @@ urlpatterns = patterns('', (r'^materials/tradenames$', 'materials.views.manufacturers'), (r'^objects/$', 'objects.views.index'), + (r'^objects/ean_lookup$', 'objects.views.ean_lookup'), (r'^xml/location', 'locations.views.locationtoxml'), (r'^yaml/location', 'locations.views.locationtoyaml'), |