{
 "schema_version": "1.0",
 "nodes": [
  { "id": "shoot", "type": "input/bundle_manifest", "label": "The hotel's photos", "parameters": { "validation": "warn", "verifyChecksum": "always", "allowExternalUrls": false, "manifest": "__SHOOT__" }, "position": { "x": 0, "y": 300 } },
  { "id": "assets", "type": "utility/extract", "label": "Files", "parameters": { "path": "assets", "expected_type": "json", "on_missing": "fail" }, "position": { "x": 300, "y": 300 } },
  { "id": "photos", "type": "enumerate/json", "label": "Each photo", "parameters": { "jsonConfig": { "arrayPath": "(root)", "properties": [ { "sourcePath": "id", "outputPort": "photo_id", "outputType": "text", "selected": true, "label": "Photo" }, { "sourcePath": "metadata.space", "outputPort": "space", "outputType": "text", "selected": true, "label": "Space" }, { "sourcePath": "storageRef", "outputPort": "photo", "outputType": "image", "selected": true, "label": "Image" } ] }, "emptyBehavior": "fail" }, "position": { "x": 600, "y": 300 } },

  { "id": "size", "type": "media/technical_info", "label": "Size", "parameters": {}, "position": { "x": 950, "y": 0 } },
  { "id": "exposure", "type": "image/statistics", "label": "Exposure", "parameters": {}, "position": { "x": 950, "y": 160 } },
  { "id": "detail", "type": "image/detail", "label": "Sharpness", "parameters": { "select": "[\"detail\"]" }, "position": { "x": 950, "y": 380 } },
  { "id": "sharpness", "type": "utility/extract", "label": "Most detailed area", "parameters": { "path": "selected[0].gradient", "expected_type": "number", "on_missing": "fail" }, "position": { "x": 1250, "y": 380 } },
  { "id": "people", "type": "image/instance_segment", "label": "People", "parameters": { "class_filter": "[\"person\"]", "score_threshold": 0.5, "output_masks": false, "check_id": "people" }, "position": { "x": 950, "y": 560 } },

  { "id": "big_enough", "type": "utility/predicate", "label": "At least 1280 px wide", "parameters": { "operation": "greater_or_equal", "compare_number": 1280 }, "position": { "x": 1550, "y": 0 } },
  { "id": "not_dark", "type": "utility/predicate", "label": "Median at least 0.15", "parameters": { "operation": "greater_or_equal", "compare_number": 0.15 }, "position": { "x": 1550, "y": 130 } },
  { "id": "not_burnt", "type": "utility/predicate", "label": "At most 2% near white", "parameters": { "operation": "less_or_equal", "compare_number": 0.02 }, "position": { "x": 1550, "y": 260 } },
  { "id": "sharp", "type": "utility/predicate", "label": "Sharpest area at least 0.15", "parameters": { "operation": "greater_or_equal", "compare_number": 0.15 }, "position": { "x": 1550, "y": 390 } },
  { "id": "no_people", "type": "utility/predicate", "label": "No one in the picture", "parameters": { "operation": "equals", "compare_number": 0 }, "position": { "x": 1550, "y": 520 } },
  { "id": "ready", "type": "utility/boolean_combine", "label": "Every check passes", "parameters": { "mode": "all" }, "position": { "x": 1850, "y": 260 } },

  { "id": "keep", "type": "utility/filter", "label": "Only the ready ones", "parameters": { "invert": false }, "position": { "x": 2150, "y": 160 } },
  { "id": "sized", "type": "image/resize", "label": "1280 × 720 for the portal", "parameters": { "width": 1280, "height": 720, "mode": "fill", "never_enlarge": true }, "position": { "x": 2450, "y": 160 } },
  { "id": "reason", "type": "text/expression", "label": "Reason", "parameters": { "expression": "{{~ r = [] ~}}{{~ if !big_enough; r = r | array.add (\"too small: \" + width + \" px wide\"); end ~}}{{~ if !not_dark; r = r | array.add (\"too dark: median brightness \" + (median | math.round 2)); end ~}}{{~ if !not_burnt; r = r | array.add (\"burnt: \" + (white | math.format \"0.0%\") + \" of the picture is near white\"); end ~}}{{~ if not_dark && !sharp; r = r | array.add (\"not sharp: the most detailed area only reaches \" + (sharpness | math.round 2)); end ~}}{{~ if !no_people; r = r | array.add (people + \" people in the picture\"); end ~}}{{~ if r.size == 0 ~}}ready{{~ else ~}}{{ r | array.join \"; \" }}{{~ end ~}}" }, "position": { "x": 2150, "y": 480 } },

  { "id": "listing", "type": "aggregate/json", "label": "Ready for the portal", "parameters": { "emptyBehavior": "empty", "jsonAggregateConfig": { "prettyPrint": true, "outputName": "listing", "columns": [ { "name": "photo", "inputPort": "photo_id", "type": "text" }, { "name": "space", "inputPort": "space", "type": "text" }, { "name": "image", "inputPort": "image", "type": "image", "whenAbsent": "skip_row" } ] } }, "position": { "x": 2750, "y": 160 } },
  { "id": "report", "type": "aggregate/json", "label": "Screening report", "parameters": { "jsonAggregateConfig": { "prettyPrint": true, "outputName": "screening", "columns": [ { "name": "photo", "inputPort": "photo_id", "type": "text" }, { "name": "space", "inputPort": "space", "type": "text" }, { "name": "width", "inputPort": "width", "type": "number" }, { "name": "median_brightness", "inputPort": "median", "type": "number" }, { "name": "near_white", "inputPort": "white", "type": "number" }, { "name": "sharpness", "inputPort": "sharpness", "type": "number" }, { "name": "people", "inputPort": "people", "type": "number" }, { "name": "ready", "inputPort": "ready", "type": "boolean" }, { "name": "reason", "inputPort": "reason", "type": "text" } ] } }, "position": { "x": 2450, "y": 480 } },

  { "id": "out_photos", "type": "output/image", "label": "Photos for the portal", "parameters": { "output_name": "photos" }, "position": { "x": 2750, "y": 0 } },
  { "id": "out_listing", "type": "output/json", "label": "Listing", "parameters": { "output_name": "listing" }, "position": { "x": 3050, "y": 160 } },
  { "id": "out_report", "type": "output/json", "label": "Screening report", "parameters": { "output_name": "screening_report" }, "position": { "x": 2750, "y": 480 } },
  { "id": "out_issues", "type": "output/json", "label": "Bundle issues", "parameters": { "output_name": "bundle_issues" }, "position": { "x": 300, "y": 480 } }
 ],
 "connections": [
  { "from_node": "shoot", "from_output": "bundle", "to_node": "assets", "to_input": "json" },
  { "from_node": "assets", "from_output": "value", "to_node": "photos", "to_input": "json" },
  { "from_node": "shoot", "from_output": "issues", "to_node": "out_issues", "to_input": "json" },

  { "from_node": "photos", "from_output": "photo", "to_node": "size", "to_input": "media" },
  { "from_node": "photos", "from_output": "photo", "to_node": "exposure", "to_input": "image" },
  { "from_node": "photos", "from_output": "photo", "to_node": "detail", "to_input": "image" },
  { "from_node": "detail", "from_output": "detail", "to_node": "sharpness", "to_input": "json" },
  { "from_node": "photos", "from_output": "photo", "to_node": "people", "to_input": "image" },

  { "from_node": "size", "from_output": "width", "to_node": "big_enough", "to_input": "a" },
  { "from_node": "exposure", "from_output": "median_luma", "to_node": "not_dark", "to_input": "a" },
  { "from_node": "exposure", "from_output": "clipped_white", "to_node": "not_burnt", "to_input": "a" },
  { "from_node": "sharpness", "from_output": "value", "to_node": "sharp", "to_input": "a" },
  { "from_node": "people", "from_output": "count", "to_node": "no_people", "to_input": "a" },
  { "from_node": "big_enough", "from_output": "result", "to_node": "ready", "to_input": "conditions_0" },
  { "from_node": "not_dark", "from_output": "result", "to_node": "ready", "to_input": "conditions_1" },
  { "from_node": "not_burnt", "from_output": "result", "to_node": "ready", "to_input": "conditions_2" },
  { "from_node": "sharp", "from_output": "result", "to_node": "ready", "to_input": "conditions_3" },
  { "from_node": "no_people", "from_output": "result", "to_node": "ready", "to_input": "conditions_4" },

  { "from_node": "ready", "from_output": "result", "to_node": "keep", "to_input": "condition" },
  { "from_node": "photos", "from_output": "photo", "to_node": "keep", "to_input": "value" },
  { "from_node": "keep", "from_output": "value", "to_node": "sized", "to_input": "image" },

  { "from_node": "size", "from_output": "width", "to_node": "reason", "to_input": "width" },
  { "from_node": "exposure", "from_output": "median_luma", "to_node": "reason", "to_input": "median" },
  { "from_node": "exposure", "from_output": "clipped_white", "to_node": "reason", "to_input": "white" },
  { "from_node": "sharpness", "from_output": "value", "to_node": "reason", "to_input": "sharpness" },
  { "from_node": "people", "from_output": "count", "to_node": "reason", "to_input": "people" },
  { "from_node": "big_enough", "from_output": "result", "to_node": "reason", "to_input": "big_enough" },
  { "from_node": "not_dark", "from_output": "result", "to_node": "reason", "to_input": "not_dark" },
  { "from_node": "not_burnt", "from_output": "result", "to_node": "reason", "to_input": "not_burnt" },
  { "from_node": "sharp", "from_output": "result", "to_node": "reason", "to_input": "sharp" },
  { "from_node": "no_people", "from_output": "result", "to_node": "reason", "to_input": "no_people" },

  { "from_node": "photos", "from_output": "photo_id", "to_node": "listing", "to_input": "photo_id" },
  { "from_node": "photos", "from_output": "space", "to_node": "listing", "to_input": "space" },
  { "from_node": "sized", "from_output": "result", "to_node": "listing", "to_input": "image" },
  { "from_node": "sized", "from_output": "result", "to_node": "out_photos", "to_input": "image" },
  { "from_node": "listing", "from_output": "result", "to_node": "out_listing", "to_input": "json" },

  { "from_node": "photos", "from_output": "photo_id", "to_node": "report", "to_input": "photo_id" },
  { "from_node": "photos", "from_output": "space", "to_node": "report", "to_input": "space" },
  { "from_node": "size", "from_output": "width", "to_node": "report", "to_input": "width" },
  { "from_node": "exposure", "from_output": "median_luma", "to_node": "report", "to_input": "median" },
  { "from_node": "exposure", "from_output": "clipped_white", "to_node": "report", "to_input": "white" },
  { "from_node": "sharpness", "from_output": "value", "to_node": "report", "to_input": "sharpness" },
  { "from_node": "people", "from_output": "count", "to_node": "report", "to_input": "people" },
  { "from_node": "ready", "from_output": "result", "to_node": "report", "to_input": "ready" },
  { "from_node": "reason", "from_output": "text", "to_node": "report", "to_input": "reason" },
  { "from_node": "report", "from_output": "result", "to_node": "out_report", "to_input": "json" }
 ]
}
