Appendix: Complete code for all projects

  1. Project 1. Does the photo contain a certain object?
  2. Project 2. Find a similar item in an online store
  3. Project 3. Does the item found look similar to the original?
  4. Project 4. Which of the found items is most similar to the original?

Project 1. Does the photo contain a certain object?

Specifications:

Input:
{   "image": {     "type": "url",     "hidden": false,     "required": true   } }
Copied to clipboard
Output:
{   "result": {     "type": "string",     "hidden": false,     "required": true   } }
Copied to clipboard
Input:
{   "image": {     "type": "url",     "hidden": false,     "required": true   } }
Copied to clipboard
Output:
{   "result": {     "type": "string",     "hidden": false,     "required": true   } }
Copied to clipboard

HTML:

{{img src=image width="100%" height="400px"}} <div>Are there <b>shoes</b> in the picture?<div>
<div> {{field type="radio" name="result" value="OK" label="Да" hotkey="1"}}
{{field type="radio" name="result" value="BAD" label="Нет" hotkey="2"}}
{{field type="radio" name="result" value="404" label="Ошибка загрузки" hotkey="3"}}</div>
Copied to clipboard

JavaScript:

exports.Task = extend(TolokaHandlebarsTask, function(options) {
    TolokaHandlebarsTask.call(this, options);
}, {
    onRender: function() {
        // DOM element for task is formed (available via #getDOMElement()) 
    },
    onDestroy: function() {
        // Task is completed. Global resources can be released (if used)
    }
});

function extend(ParentClass, constructorFunction, prototypeHash) {
    constructorFunction = constructorFunction || function() {};
    prototypeHash = prototypeHash || {};
    if (ParentClass) {
        constructorFunction.prototype = Object.create(ParentClass.prototype);
    }
    for (var i in prototypeHash) {
        constructorFunction.prototype[i] = prototypeHash[i];
    }
    return constructorFunction;
}
Copied to clipboard

Project 2. Find a similar item in an online store

Specifications:

Input:

{   "image": {     "type": "url",     "hidden": false,     "required": true   } }
Copied to clipboard

Output:

{
  "button": {
    "type": "boolean",
    "hidden": false,
    "required": true,
    "allowed_values": [
      true
    ]
  },
  "found_link": {
    "type": "string",
    "hidden": false,
    "pattern": "https://www.asos.com/.*",
    "required": true
  },
  "found_image": {
    "type": "file",
    "hidden": false,
    "required": true
  }
}
Copied to clipboard

Input:

{   "image": {     "type": "url",     "hidden": false,     "required": true   } }
Copied to clipboard

Output:

{
  "button": {
    "type": "boolean",
    "hidden": false,
    "required": true,
    "allowed_values": [
      true
    ]
  },
  "found_link": {
    "type": "string",
    "hidden": false,
    "pattern": "https://www.asos.com/.*",
    "required": true
  },
  "found_image": {
    "type": "file",
    "hidden": false,
    "required": true
  }
}
Copied to clipboard

HTML:

{{img src=image width="50%" height="400px"}}
<div class='answers'>
 <p>Find similar <b>shoes</b> in the ASOS online store</p>
 {{field type="button-clicked" name="button" label="ASOS" href="https://www.asos.com" action=true}}
 <p>The shoes must be similar in color, material, length, and style</p>
 <p>Paste the link here</p>
 {{field width="100%" type="input" name="found_link"}}
 <p>Upload the image here</p>
 <div>
 {{field width="100%" type="file-img" name="found_image" preview=true}}
 </div>
</div>
Copied to clipboard

JavaScript:

exports.Task = extend(TolokaHandlebarsTask, function(options) {
    TolokaHandlebarsTask.call(this, options);
}, {
    validate: function(solution) {

        if (!solution.output_values.found_image) {

            return {
                task_id: this.getTask().id,
                errors: {
                    '__TASK__': {
                        message: 'Upload photo or mark that there is no photo'
                    }
                }
            };
        } else {
            return TolokaHandlebarsTask.prototype.validate.apply(this, arguments);
        }
    },
    onRender: function() {
        // DOM element for task is formed (available via #getDOMElement()) 
    },
    onDestroy: function() {
        // Task is completed. Global resources can be released (if used)
    }
});

function extend(ParentClass, constructorFunction, prototypeHash) {
    constructorFunction = constructorFunction || function() {};
    prototypeHash = prototypeHash || {};
    if (ParentClass) {
        constructorFunction.prototype = Object.create(ParentClass.prototype);
    }
    for (var i in prototypeHash) {
        constructorFunction.prototype[i] = prototypeHash[i];
    }
    return constructorFunction;
}
Copied to clipboard

CSS:

.task {
    display: block;
    height: 500px;
    width: 800px;
}

.img {
    float: left;
    width: 50%;
}

.answers {
    float: left;
    width: 40%;
    margin: 5%;
}
Copied to clipboard

Project 3. Does the item found look similar to the original?

Specifications:

Input:

{
  "image": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "found_link": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "assignment_id": {
    "type": "string",
    "hidden": true,
    "required": true
  }
}
Copied to clipboard

Output:

{   "result": {     "type": "string",     "hidden": false,     "required": true   } }
Copied to clipboard

Input:

{
  "image": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "found_link": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "assignment_id": {
    "type": "string",
    "hidden": true,
    "required": true
  }
}
Copied to clipboard

Output:

{   "result": {     "type": "string",     "hidden": false,     "required": true   } }
Copied to clipboard

HTML:

{{img src=image height="400px"}}
{{iframe src= found_link height="600px"}}

    <p>Check that the uploaded image matches the product in the store.</p>
  {{button label="Проверьте товар" href=found_link action=true}}   <p>Are <b>these shoes</b> similar to each other?</p>  <p>The shoes must be similar in color, material, length, and style.</p>    {{field type="radio" name="result" value="Yes" label="Да"}}{{field type="radio" name="result" value="No" label="Нет"}}
Copied to clipboard

JavaScript:

exports.Task = extend(TolokaHandlebarsTask, function(options) {
    TolokaHandlebarsTask.call(this, options);
}, {
    onRender: function() {
        // DOM element for task is formed (available via #getDOMElement()) 
    },
    onDestroy: function() {
        // Task is completed. Global resources can be released (if used)
    }
});

function extend(ParentClass, constructorFunction, prototypeHash) {
    constructorFunction = constructorFunction || function() {};
    prototypeHash = prototypeHash || {};
    if (ParentClass) {
        constructorFunction.prototype = Object.create(ParentClass.prototype);
    }
    for (var i in prototypeHash) {
        constructorFunction.prototype[i] = prototypeHash[i];
    }
    return constructorFunction;
}
Copied to clipboard
CSS:
.task {
    display: block;
}

.img {
    float: left;
    width: 50%;
}

.iframe {
    float: left;
    width: 50%;
}
Copied to clipboard

Project 4. Which of the found items is most similar to the original?

Specifications:

Input:

{
  "image": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "left_link": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "right_link": {
    "type": "url",
    "hidden": false,
    "required": true
  }
}
Copied to clipboard

Output:

{
  "result": {
    "type": "url",
    "hidden": false,
    "required": true
  }
}
Copied to clipboard

Input:

{
  "image": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "left_link": {
    "type": "url",
    "hidden": false,
    "required": true
  },
  "right_link": {
    "type": "url",
    "hidden": false,
    "required": true
  }
}
Copied to clipboard

Output:

{
  "result": {
    "type": "url",
    "hidden": false,
    "required": true
  }
}
Copied to clipboard

HTML:

<div class="header">
    <div class="left caption"> {{button label="Перейдите на сайт" href=left_link size="L"}}
        <p class="url">{{left_link}}</p>
    </div>
    <div class="right caption">
        <p class="url">{{right_link}}</p>
        {{button label="Перейдите на сайт" href=right_link size="L"}}
    </div>
</div> {{img src=image}}
<div class="content clearfix">
    <div class="left page">
        {{iframe src=uploaded_link_left width="100%" height="700px" real-size=true screenshot=true}}
    </div>
    <div class="right page">
        {{iframe src=uploaded_link_right width="100%" height="700px" real-size=true screenshot=true}}
    </div>
</div>
<div class="footer">
    {{field type="radio" name="result" label="Левое изображение лучше" value=result_left hotkey="1"}}
    {{field type="radio" name="result" label="Правое изображение лучше" value=result_right hotkey="2"}}
</div>
Copied to clipboard

JavaScript:

exports.Task = extend(TolokaHandlebarsTask, function(options) {
    TolokaHandlebarsTask.call(this, options);
}, {
    getTemplateData: function() {
        var data = TolokaHandlebarsTask.prototype.getTemplateData.apply(this, arguments),
            input = this.getTask().input_values;
        var left_link = input.left_link;
        var right_link = input.right_link;
        var uploaded_link_left = '',
            uploaded_link_right = ''
        if (Math.floor(Math.random() * 2)) {
            uploaded_link_left = left_link
            uploaded_link_right = right_link
        } else {
            uploaded_link_left = right_link
            uploaded_link_right = left_link
        }
        data.uploaded_link_left = uploaded_link_left;
        data.uploaded_link_right = uploaded_link_right;
        data.result_left = uploaded_link_left;
        data.result_right = uploaded_link_right;

        return data;

    },

    onRender: function() {
        // DOM element for task is formed (available via #getDOMElement()) 
    },
    onDestroy: function() {
        // Task is completed. Global resources can be released (if used)
    }
});

function extend(ParentClass, constructorFunction, prototypeHash) {
    constructorFunction = constructorFunction || function() {};
    prototypeHash = prototypeHash || {};
    if (ParentClass) {
        constructorFunction.prototype = Object.create(ParentClass.prototype);
    }
    for (var i in prototypeHash) {
        constructorFunction.prototype[i] = prototypeHash[i];
    }
    return constructorFunction;
}
Copied to clipboard
CSS:
.task {
    display: block;
    text-align: center;
}

.header {
    overflow: hidden;
    background-color: #FFCC00;
}

.caption {
    width: 50%;
}

.url {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    max-width: calc(100% - 182px);

    display: inline-block;
    vertical-align: bottom;
}

.button {
    margin: 10px;
    max-width: 182px;
}


.content {
    margin: 10px 0;
}

.page {
    display: inline-block;
    width: 50%;
}

.left {
    float: left;
    text-align: left;
}

.right {
    float: right;
    text-align: right;
}

.clearfix {
    overflow: hidden;
    width: 100%;
}


.image {
    display: inline-block;
    width: 50%;
}.task {
    display: block;
    text-align: center;
}

.header {
    overflow: hidden;
    background-color: #FFCC00;
}

.caption {
    width: 50%;
}

.url {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    max-width: calc(100% - 182px);

    display: inline-block;
    vertical-align: bottom;
}

.button {
    margin: 10px;
    max-width: 182px;
}


.content {
    margin: 10px 0;
}

.page {
    display: inline-block;
    width: 50%;
}

.left {
    float: left;
    text-align: left;
}

.right {
    float: right;
    text-align: right;
}

.clearfix {
    overflow: hidden;
    width: 100%;
}

.image {
    display: inline-block;
    width: 50%;
}
Copied to clipboard