{
 "schema_version": "1.0",
 "nodes": [
  { "id": "crew", "type": "input/bundle_manifest", "label": "Everyone's photo", "parameters": { "validation": "warn", "verifyChecksum": "always", "allowExternalUrls": false, "manifest": "__CREW__" }, "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": "members", "type": "enumerate/json", "label": "Each member", "parameters": { "jsonConfig": { "arrayPath": "(root)", "properties": [ { "sourcePath": "id", "outputPort": "member_id", "outputType": "text", "selected": true, "label": "Member" }, { "sourcePath": "metadata.name", "outputPort": "name", "outputType": "text", "selected": true, "label": "Name" }, { "sourcePath": "metadata.role", "outputPort": "role", "outputType": "text", "selected": true, "label": "Role" }, { "sourcePath": "storageRef", "outputPort": "photo", "outputType": "image", "selected": true, "label": "Photo" } ] }, "emptyBehavior": "fail" }, "position": { "x": 600, "y": 300 } },

  { "id": "faces", "type": "image/face_detect", "label": "Find the face", "parameters": { "framing": "head", "aspect": "1:1", "check_id": "has-face" }, "position": { "x": 950, "y": 160 } },
  { "id": "whole", "type": "image/statistics", "label": "Tone of the photo", "parameters": {}, "position": { "x": 950, "y": 480 } },
  { "id": "score", "type": "utility/extract", "label": "Face score", "parameters": { "path": "faces[0].score", "expected_type": "number", "on_missing": "absent" }, "position": { "x": 1250, "y": 640 } },
  { "id": "gate", "type": "utility/quality_gate", "label": "Only with a face", "parameters": { "profile": "all_must_pass", "mode": "route" }, "position": { "x": 1250, "y": 160 } },

  { "id": "crop", "type": "image/crop", "label": "Head shot", "parameters": {}, "position": { "x": 1550, "y": 0 } },
  { "id": "shot", "type": "image/resize", "label": "300 × 300", "parameters": { "width": 300, "height": 300, "mode": "fill" }, "position": { "x": 1850, "y": 0 } },
  { "id": "tone", "type": "image/statistics", "label": "Tone of the face", "parameters": {}, "position": { "x": 1550, "y": 240 } },
  { "id": "face_tone", "type": "utility/extract", "label": "Face median", "parameters": { "path": "regions[0].luma.p50", "expected_type": "number", "on_missing": "fail" }, "position": { "x": 1850, "y": 240 } },
  { "id": "lit", "type": "utility/predicate", "label": "Face median at least 0.35", "parameters": { "operation": "greater_or_equal", "compare_number": 0.35 }, "position": { "x": 2150, "y": 180 } },
  { "id": "not_glaring", "type": "utility/predicate", "label": "Face median at most 0.75", "parameters": { "operation": "less_or_equal", "compare_number": 0.75 }, "position": { "x": 2150, "y": 310 } },
  { "id": "tone_ok", "type": "utility/boolean_combine", "label": "Face well lit", "parameters": { "mode": "all" }, "position": { "x": 2450, "y": 240 } },
  { "id": "on_page", "type": "utility/filter", "label": "On the page", "parameters": { "invert": false }, "position": { "x": 2750, "y": 0 } },
  { "id": "to_send", "type": "utility/filter", "label": "No face: ask for a portrait", "parameters": { "invert": true }, "position": { "x": 1250, "y": 820 } },

  { "id": "page_list", "type": "aggregate/json", "label": "The crew on the page", "parameters": { "emptyBehavior": "fail", "jsonAggregateConfig": { "prettyPrint": true, "outputName": "crew", "columns": [ { "name": "name", "inputPort": "name", "type": "text" }, { "name": "role", "inputPort": "role", "type": "text" }, { "name": "photo", "inputPort": "photo", "type": "image", "whenAbsent": "skip_row" } ] } }, "position": { "x": 3050, "y": 0 } },
  { "id": "missing", "type": "aggregate/json", "label": "Portraits to ask for", "parameters": { "emptyBehavior": "empty", "jsonAggregateConfig": { "prettyPrint": true, "outputName": "portraits_to_ask_for", "columns": [ { "name": "name", "inputPort": "name", "type": "text", "whenAbsent": "skip_row" }, { "name": "role", "inputPort": "role", "type": "text" } ] } }, "position": { "x": 1550, "y": 820 } },
  { "id": "report", "type": "aggregate/json", "label": "Report", "parameters": { "jsonAggregateConfig": { "prettyPrint": true, "outputName": "report", "columns": [ { "name": "member", "inputPort": "member_id", "type": "text" }, { "name": "name", "inputPort": "name", "type": "text" }, { "name": "face_found", "inputPort": "found", "type": "boolean" }, { "name": "face_score", "inputPort": "face_score", "type": "number", "whenAbsent": "null" }, { "name": "face_median", "inputPort": "face_median", "type": "number", "whenAbsent": "null" }, { "name": "photo_median", "inputPort": "photo_median", "type": "number" }, { "name": "on_page", "inputPort": "on_page", "type": "boolean", "whenAbsent": "null" } ] } }, "position": { "x": 2750, "y": 560 } },

  { "id": "page", "type": "design/template_render", "label": "The crew page", "parameters": { "template_id": "__TEMPLATE_ID__", "template_revision": "__TEMPLATE_REVISION__", "output": "both", "missing_policy": "fail_required", "overflow_policy": "template", "max_repeat": 9 }, "position": { "x": 3350, "y": 0 } },

  { "id": "out_page_image", "type": "output/image", "label": "Page", "parameters": { "output_name": "page" }, "position": { "x": 3650, "y": 0 } },
  { "id": "out_page_pdf", "type": "output/pdf", "label": "Page PDF", "parameters": { "output_name": "page_pdf" }, "position": { "x": 3650, "y": 140 } },
  { "id": "out_shots", "type": "output/image", "label": "Head shots", "parameters": { "output_name": "head_shots" }, "position": { "x": 2150, "y": 0 } },
  { "id": "out_missing", "type": "output/json", "label": "Portraits to ask for", "parameters": { "output_name": "portraits_to_ask_for" }, "position": { "x": 1850, "y": 820 } },
  { "id": "out_report", "type": "output/json", "label": "Report", "parameters": { "output_name": "report" }, "position": { "x": 3050, "y": 560 } },
  { "id": "out_issues", "type": "output/json", "label": "Bundle issues", "parameters": { "output_name": "bundle_issues" }, "position": { "x": 300, "y": 480 } }
 ],
 "connections": [
  { "from_node": "crew", "from_output": "bundle", "to_node": "assets", "to_input": "json" },
  { "from_node": "assets", "from_output": "value", "to_node": "members", "to_input": "json" },
  { "from_node": "crew", "from_output": "issues", "to_node": "out_issues", "to_input": "json" },

  { "from_node": "members", "from_output": "photo", "to_node": "faces", "to_input": "image" },
  { "from_node": "members", "from_output": "photo", "to_node": "whole", "to_input": "image" },
  { "from_node": "faces", "from_output": "faces", "to_node": "score", "to_input": "json" },
  { "from_node": "faces", "from_output": "quality_check", "to_node": "gate", "to_input": "checks_0" },
  { "from_node": "members", "from_output": "photo", "to_node": "gate", "to_input": "value" },

  { "from_node": "gate", "from_output": "value", "to_node": "crop", "to_input": "image" },
  { "from_node": "faces", "from_output": "crop_region", "to_node": "crop", "to_input": "region" },
  { "from_node": "crop", "from_output": "result", "to_node": "shot", "to_input": "image" },
  { "from_node": "gate", "from_output": "value", "to_node": "tone", "to_input": "image" },
  { "from_node": "faces", "from_output": "faces", "to_node": "tone", "to_input": "regions" },
  { "from_node": "tone", "from_output": "statistics", "to_node": "face_tone", "to_input": "json" },
  { "from_node": "face_tone", "from_output": "value", "to_node": "lit", "to_input": "a" },
  { "from_node": "face_tone", "from_output": "value", "to_node": "not_glaring", "to_input": "a" },
  { "from_node": "lit", "from_output": "result", "to_node": "tone_ok", "to_input": "conditions_0" },
  { "from_node": "not_glaring", "from_output": "result", "to_node": "tone_ok", "to_input": "conditions_1" },
  { "from_node": "tone_ok", "from_output": "result", "to_node": "on_page", "to_input": "condition" },
  { "from_node": "shot", "from_output": "result", "to_node": "on_page", "to_input": "value" },
  { "from_node": "shot", "from_output": "result", "to_node": "out_shots", "to_input": "image" },

  { "from_node": "faces", "from_output": "found", "to_node": "to_send", "to_input": "condition" },
  { "from_node": "members", "from_output": "name", "to_node": "to_send", "to_input": "value" },
  { "from_node": "to_send", "from_output": "value", "to_node": "missing", "to_input": "name" },
  { "from_node": "members", "from_output": "role", "to_node": "missing", "to_input": "role" },
  { "from_node": "missing", "from_output": "result", "to_node": "out_missing", "to_input": "json" },

  { "from_node": "members", "from_output": "name", "to_node": "page_list", "to_input": "name" },
  { "from_node": "members", "from_output": "role", "to_node": "page_list", "to_input": "role" },
  { "from_node": "on_page", "from_output": "value", "to_node": "page_list", "to_input": "photo" },
  { "from_node": "page_list", "from_output": "result", "to_node": "page", "to_input": "crew" },
  { "from_node": "page", "from_output": "image", "to_node": "out_page_image", "to_input": "image" },
  { "from_node": "page", "from_output": "pdf", "to_node": "out_page_pdf", "to_input": "pdf" },

  { "from_node": "members", "from_output": "member_id", "to_node": "report", "to_input": "member_id" },
  { "from_node": "members", "from_output": "name", "to_node": "report", "to_input": "name" },
  { "from_node": "faces", "from_output": "found", "to_node": "report", "to_input": "found" },
  { "from_node": "score", "from_output": "value", "to_node": "report", "to_input": "face_score" },
  { "from_node": "face_tone", "from_output": "value", "to_node": "report", "to_input": "face_median" },
  { "from_node": "whole", "from_output": "median_luma", "to_node": "report", "to_input": "photo_median" },
  { "from_node": "tone_ok", "from_output": "result", "to_node": "report", "to_input": "on_page" },
  { "from_node": "report", "from_output": "result", "to_node": "out_report", "to_input": "json" }
 ]
}
