/HCBackend

Primary LanguageJavaScriptMIT LicenseMIT

HCBackend

Storage Backend for Human Computation application.

This application allow to Store, Retrieve and Update data related to Human Computation tasks using REST APIs.

Developed By Carlo Bernaschina (GitHub - B3rn475)
www.bernaschina.com

Copyright (c) 2014 Politecnico di Milano
www.polimi.it

Distributed under the MIT License

Headers

In order to allow future modifications it has been chosen to force the remote Host to choose the output format of the APIs.

This is done using the Accept HTTP Header.

Accepted Formats:

  • application/json

If the header is not set as a common Web Application is goes for the default text/html format, that is currently non implemented.

If you receive a 501 : not implemented error first check the Accept Header of your request.

HTTP Methods

The main idea is to use the right HTTP Method for the operation.

  • GET to obtain data
  • POST to add new data or to do one time operations
  • PUT to update elements
  • DELETE to remove items

Stored Objects

Image

fields:

  • id: { type: Number, min: 0, index: { unique: true }}
  • width: { type: Number, min: 1}
  • height: { type: Number, min: 1}
  • mediaLocator: {type: String} // virtual
  • pose: []
    • location: {type: String, enum: ["head", "torso", "left_arm", "right_arm", "legs", "feet"]},
    • x0 : { type: Number, min: 0, max: width - 1},
    • y0 : { type: Number, min: 0, max: height - 1},
    • x1 : { type: Number, min: 0, max: width - 1},
    • y1 : { type: Number, min: 0, max: height - 1}

Collection

fields:

  • id: { type: Number, min: 0, index: { unique: true }}
  • name: {type: String, validate: /[a-zA-Z ]+$/}
  • images : [ Image ]

Tag

fields:

  • id: { type: Number, min: 0, index: { unique: true }, select: false}
  • name: {type: String, validate: /[a-zA-Z ]+$/}
  • aliases: []
    • language: {type: String, validate: /[a-z]{2}-[A-Z]{2}$/}
    • name: {type: String, validate: /[a-zA-Z ]+$/}

User

fields:

  • id: { type: Number, min: 0, index: { unique: true }}
  • app_id: { type: Number, min: 0}
  • app_user_id: { type: String}
  • quality: { type: Number}
  • statistics : { sessions: {type: Number} actions: {type: Number} }

Mask

fields:

  • id: { type: Number, min: 0, index: { unique: true }},
  • image: Image
  • tag: Tag
  • quality: { type: Number}
  • segmentations: { type: Number, min: 1}
  • updated_at: {type: Date}
  • mediaLocator: {type: String} // virtual

Session

fields:

  • id: { type: Number, min: 0, index: { unique: true }}
  • created_at: {type: Date}
  • completed_at: {type: Date}

Action

fields:

  • id: { type: Number, min: 0, index: { unique: true }},
  • session: Session
  • image: Image
  • tag: Tag
  • user: User
  • type: {type: String, enum: ["tagging", "segmentation", "upload"]},
  • segmentation:
    • quality: { type: Number}
    • points: []
      • x: { type: Number, min: 0}
      • y: { type: Number, min: 0}
      • end: { type: Boolean: default: undefined}
    • history: []
      • size: {type: Number, min: 1}
      • color: {type: String, validate: /(rgb(([0-1][0-9]{2}|2[0-4][0-9]|25[0-5]|[0-9]{2}|[0-9]),[ ]([0-1][0-9]{2}|2[0-4][0-9]|25[0-5]|[0-9]{2}|[0-9]),[ ]([0-1][0-9]{2}|2[0-4][0-9]|25[0-5]|[0-9]{2}|[0-9])))|(rgba(([0-1][0-9]{2}|2[0-4][0-9]|25[0-5]|[0-9]{2}|[0-9]),[ ]([0-1][0-9]{2}|2[0-4][0-9]|25[0-5]|[0-9]{2}|[0-9]),[ ]([0-1][0-9]{2}|2[0-4][0-9]|25[0-5]|[0-9]{2}|[0-9]),[ ]*(1|0|1.0|0.[0-9]+)))/}
      • time : {type:Number, min 0}
      • points: []
        • x: { type: Number}
        • y: { type: Number}
  • started_at: {type: Date},
  • completed_at: {type: Date},
  • validity: {type: Boolean, default: true}

for tagging:
tag can be present or not. If it is present the action is completed otherwise skipped
segmentation is not present

for segmentation:
tag is always present. segmentation can be present or not. If it is present the action is completed otherwise skipped

Task

fields:

  • id: { type: Number, min: 0, index: { unique: true }}
  • image: [ Image ]
  • users : [ User ]
  • created_at: {type: Date}
  • completed_at: {type: Date}

Microtask

fields:

  • id: { type: Number, min: 0, index: { unique: true }}
  • type: {type: String, enum: ["tagging", "segmentation"]}
  • task: Task
  • action: Action
  • order: {type: Number, min: 0}
  • created_at: {type: Date}
  • completed_at: {type: Date}

Error Handling

JSON

If there is an error during the process, due to a Bad Route, a Missing or Wrong Parameter or to an Internal Server Error an error message will be returned.

Format:

{
    "status": "KO",
    "errors": [{"location": "url|body|query|status|internal", 
        "name": "parameter that has generate the error",
        "message": "description of the error"
        }]
}

Good Request

JSON

If there are not errors during the operation the following object will be sent:

{
    "status": "OK",
    ... //Other data related to the api
}

Routes

Format:

METHOD : PATH description:

  • location : name : optional|mandatory : description
  • ...

The following routes are corrently available:

GET : /
get the status of the server

Image


GET : /image
returns the list of the images

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : min_segmentations : optional : lower bound for the number of segmentations (included)
  • query : max_segmentations : optional : upper bound for the number of segmentations (included)

Example result:

{
    "status" : "OK",
    "search_metadata" : {
        "count" : 100,
        "refresh_url" : "?since_id=2&count=100"
    },
    "images" : [
        {
            "width" : 600,
            "height" : 921,
            "pose" : [],
            "id" : 2,
            "mediaLocator" : "/storage/image/2.jpg"
        },
        {
            "width" : 600,
            "height" : 921,
            "pose" : [],
            "id" : 1,
            "mediaLocator" : "/storage/image/1.jpg"
        },
        {
            "width" : 600,
            "height" : 921,
            "pose": [],
            "id": 0,
            "mediaLocator": "/storage/image/0.jpg"
        }
    ]
}

POST : /image
adds a new image

  • body : payload : optional : the content of the image encoded in Base64 (jpeg or png format)
  • body : url : optional : the url of the image (jpeg or png format)
  • body : pose : optional : pose of the image (see definition)

at least one between payload or url must be present.

Example result:

{
    "status" : "OK",
    "id" : 0
}

GET : /image/count
returns the number of images

Example result:

{
    "status" : "OK",
    "count" : 123
}

GET : /image/:imageId
returns an image

Example result:

{
    "status" : "OK",
    "image" : {
        "width" : 600,
        "height" : 921,
        "pose" : [],
        "id" : 0,
        "mediaLocator" : "/storage/image/0.jpg"
    }
}

PUT : /image/:imageId
updates the image information

  • body : pose : mandatory : pose of the image (see definition)

GET : /image/:imageId/tag
returns the list of tags related to this image

Example result:

{
    "status" : "OK",
    "search_metadata" : {
        "count" : 100,
        "refresh_url" : "?since_id=0&count=100"
    },
    "tags" : [
        {
            "aliases" : [
                {
                    "language" : "en-US",
                    "name" : "hat"
                },
                {
                    "language" : "it-IT",
                    "name" : "cappello"
                }
            ],
            "name" : "hat",
            "id" : 0
        }
    ]
}

Collection


GET : /collection
returns the list of collections

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)

POST : /collection
adds a new collection

  • body : name : mandatory : name of the collection

GET :/collection/count
returns the number of collections

GET : /collection/:collectionId
returns a collection

GET : /collection/:collectionId/task
returns the list of task related to images in the collection

POST : /collection/:collectionId/image adds an image to the collection

  • body : image : mandatory : the image to add to the collection

DELETE : /collection/:collectionId/image
remove an image from the collection

  • body : image : mandatory : the image to remove from the collection

DELETE : /collection/:collectionId/image/:imageId remove an image from the collection (same as the previous one, but with the id explicit in the url)

User


GET : /user
returns the list of users

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : app_id : optional : returns only users from a particular application
  • query : populate : optional : shows the user statistics

POST : /user
adds a new user (if it is already there returns the id)

  • body : app_id : mandatory : id of the application
  • body : app_user_id : mandatory : id of the user of the application

GET : /user/count returns the number of users

  • query : app_id : optional : counts only users from a particular application

GET : /user/:userId
returns a user

  • query : populate : optional : shows the user statistics

PUT : /user/:userId updates the user information

  • body : quality : mandatory : quality of the user

Tag


GET : /tag
returns the list of tags

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)

POST : /tag
adds a new tag

  • body : name : mandatory : name of the tag

GET : /tag/count
returns the number of tags

GET : /tag/:tagId
returns a tag

POST : /tag/:tagId/alias
adds a new alias to the tag

  • body : language : mandatory : language of the alias (ex: en-US)
  • body : name : mandatory : name of the alias

DELETE : /tag/:tagId/alias remove an alias from the tag

  • body : language : mandatory : language of the alias (ex: end-US)

DELETE : /tag/:tagId/alias/:language remove an alias from the tag (same as the previous one, but with the language explicit in the url)

Mask


GET : /mask
returns the list of masks

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : image : optional : returns only mask related to that image
  • query : tag : optional : returns only mask related to that tag

Example result:

{
    "status" : "OK",
    "search_metadata" : {
        "count" : 100,
        "refresh_url" : "?since_id=0&count=100"
    },
    "masks": [
        {
            "image" : 0,
            "tag" : 0,
            "segmentations" : 3,
            "quality" : 0.3,
            "mediaLocator" : "/storage/mask/0.png",
            "id" : 0
        }
    ]
}

POST : /mask adds a new mask

  • body : image : mandatory : the image related to the mask
  • body : tag : mandatory : the tag related to the mask
  • body : payload : mandatory : the content of the mask (png format)
  • body : segmentations : mandatory : the number of segmentations that has generated the mask
  • body : quality : mandatory : the quality of the mask

GET : /mask/count
returns the number of mask

Example result:

{
    "status" : "OK",
    "count" : 123
}
  • query : image : optional : counts only mask related to that image
  • query : tag : optional : counts only mask related to that tag

GET : /mask/:maskId
returns a mask

Example result:

{
    "status" : "OK",
    "mask": {
        "image" : 0,
        "tag" : 0,
        "segmentations" : 3,
        "quality" : 0.3,
        "mediaLocator" : "/storage/mask/0.png",
        "id" : 0
    }
}

PUT : /mask/:maskId updates a mask

  • body : payload : mandatory : the content of the mask (png format)
  • body : segmentations : mandatory : the number of segmentations that has generated the mask
  • body : quality : mandatory : the quality of the mask

Task


GET : /task
returns the list of tasks

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : image : optional : returns only tasks related to that image (cannot be used with collection)
  • query : collection : optional : returns only tasks related to images in that collection (cannot be used with image)
  • query : completed : optional : returns only open or completed tasks

POST : /task adds a new task

  • body : image : mandatory : image related to the task

GET : /task/count
returns the number of tasks

  • query : image : optional : counts only tasks related to that image (cannot be used with collection)
  • query : collection : optional : counts only tasks related to images in that collection (cannot be used with image)
  • query : completed : optional : counts only open or completed tasks

GET : /task/:taskId
returns a task

POST : /task/:taskId
complete a task (and all the related microtasks)

POST : /task/:taskId/user adds a new users related to the task

  • body : user : mandatory : the user to add

GET : /task/:taskId/microtask
returns the list of microtask related to this task (same as /microtask=:taskId)

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)

POST : /task/:taskId/microtask
adds a new microtask (the same as /microtask, but with the task id explicit in the url)

  • body : type : mandatory : the type of the microtask
  • body : order : mandatory : the order of the microtask

Session


GET : /session
returns the list of sessions

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : completed : optional : returns only open or completed sessions

POST : /session adds a new session

  • body : created_at : optional : creation date (default now)

*GET : /session/count returns the number of sessions

  • query : completed : optional : counts only open or completed sessions

GET : /session/:sessionId
returns a session

POST : /session/:sessionId
complete a session

  • body : completed_at : optional : completion date (default now)

GET : /session/:sessionId/action
returns the actions related to this session (same as /action?session=:sessionId)

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : type : optional : returns only the action of that type
  • query : image : optional : returns only the action related to that image
  • query : tag : optional : returns only the action related to that tag
  • query : completed : optional : returns only the completed or not completed actions
  • query : validity : optional : returns only the valid or not valid actions

POST : /session/:sessionId/action adds a new action to the session (the same as /action, but with the session id explicit in the url).

  • body : type : mandatory : the type of the action
  • body : user : mandatory : the user related to the action
  • body : tag : optional (for tagging) | mandatory (for segmentation) : the tag of the action
  • body : points : optional (only for segmentation) : the points of the segmentation
  • body : history : optional (only for segmentation) : the points of the segmentation

If it is a tagging action the tag is optional. If it is present the action is completed correctly otherwise it is still open.
If it is a segmentation action the tag is mandatory.
If it is a segmentation action the points and the history are optional. If they are present the action is completed correctly otherwise it is skipped.

Action


GET : /action
returns the list of actions

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : type : optional : returns only the action of that type
  • query : image : optional : returns only the action related to that image
  • query : tag : optional : returns only the action related to that tag
  • query : completed : optional : returns only the completed or not completed actions
  • query : validity : optional : returns only the valid or not valid actions
  • query : populate : optional : returns even the segmentations points

POST : /action
adds a new action

  • body : session : mandatory : session of the action
  • body : type : mandatory : the type of the action
  • body : user : mandatory : the user related to the action
  • body : tag : optional (for tagging) | mandatory (for segmentation) : the tag of the action
  • body : points : optional (only for segmentation) : the points of the segmentation
  • body : history : optional (only for segmentation) : the points of the segmentation

If it is a tagging action the tag is optional. If it is present the action is completed correctly otherwise it is skipped.
If it is a segmentation action the tag is mandatory.
If it is a segmentation action the points and the history are optional. If they are present the action is completed correctly otherwise it is skipped.

GET : /action/count
returns the number of actions

  • query : type : optional : counts only the action of that type
  • query : image : optional : counts only the action related to that image
  • query : tag : optional : counts only the action related to that tag
  • query : completed : optional : counts only the completed or not completed actions
  • query : validity : optional : counts only the valid or not valid actions

GET : /action/:actionId
returns an action

POST : /action/:actionId
completes the action

  • body : tag : optional (only for tagging) : the tag of the action
  • body : points : optional (only for segmentation) : the points of the segmentation
  • body : history : optional (only for segmentation) : the history of the segmentation

If it is a tagging action and the tag is not present the action is skipped. If it is a segmentation action and the points are not present the action is skipped.

PUT : /action/:actionId
updates an action

  • body : validity : optional : the new validity of the action
  • body : quality : optional : the new quality of the action

Microtask


GET : /microtask
returns the list of microtasks

  • query : count : optional : max number of items to returns (max: 100)
  • query : max_id : optional : upper bound for the id to returns (included)
  • query : since_id : optional : lower bound for the id to returns (not included)
  • query : task : __optional : returns only the microtasks related to that task
  • query : completed : __optional : returns only the open or completed tasks

POST : /microtask
adds a new microtask

  • body : task : mandatory : the task of the microtask
  • body : type : mandatory : the type of the microtask
  • body : order : mandatory : the order of the microtask

GET : /microtask/count
returns the number of microtasks

  • query : task : __optional : counts only the microtasks related to that task
  • query : completed : __optional : counts only the open or completed tasks

GET : /microtask/:microtaskId
returns a microtask

POST : /microtask/:microtaskId
complete a microtask

  • body : action : mandatory : the action that executes the task

Choose Routes


GET : /choose returns the list of the available objects to choose

GET : /choose/image returns the list of the available algorithms to choose images

GET : /choose/image/random choose a random image

  • query : limit : optional : number of elements to return (default: 1, max: 100)
  • query : collection : optional : collection from which take the images

GET : /choose/image/leastused choose the least used image

  • query : limit : optional : number of elements to return (default: 1, max: 100)
  • query : collection : optional : collection from which take the images

GET : /choose/imageandtag returns the list of the available algorithms to choose image and tag pairs

GET : /choose/imageandtag/random choose a random combination of image and tag that has already been tagged by a user

  • query : limit : optional : number of elements to return (default: 1, max: 100)
  • query : collection : optional : collection from which take the images

GET : /choose/imageandtag/leastused choose the least used combination of image and tag that has already been tagged by a user.

  • query : limit : optional : number of elements to return (default: 1, max: 100)
  • query : collection : optional : collection from which take the images

actions open from more than 1 hour are considered skipped from this route.

Statistics Routes


GET : /statistics returns statistics about the system