"use strict";(self.webpackChunkplaycanvas_game=self.webpackChunkplaycanvas_game||[]).push([[314],{314:(e,t,i)=>{i.r(t),i.d(t,{default:()=>a});var o=i(96);const a={id:"fracture_reduction",title:"Fracture Reduction Surgery",type:"scene",async build(e,t,i){console.log("[FractureReduction] Building orthopedic surgery simulation...");const a=new o.n(e,e.systems?.core);a.sceneBuilder=t,a.entityFactory=i,this.fractureData={fragmentPositions:[],originalAlignment:null,currentAlignment:null,reductionQuality:0,angulation:{x:0,y:0,z:0},displacement:{x:0,y:0,z:0},rotation:{x:0,y:0,z:0},stabilization:!1,fluoroscopyImages:0,surgicalTime:0,patientVitals:{stable:!0,painLevel:7}},this.geometricData={currentShape:"square",selectedPattern:null,fragments:[],assemblyProgress:0,practiceAttempts:0,fracturePatterns:{square:[{name:"rectangles",fragments:["rect_left","rect_right"],description:"Split into 2 rectangles"},{name:"triangles",fragments:["tri_top","tri_bottom"],description:"Diagonal split into 2 triangles"},{name:"mini_squares",fragments:["sq_tl","sq_tr","sq_bl","sq_br"],description:"Quarter into 4 mini-squares"},{name:"center_circle",fragments:["circle_center","tri_top","tri_right","tri_bottom","tri_left"],description:"Center circle + 4 corner triangles"}],triangle:[{name:"mini_triangles",fragments:["tri_1","tri_2","tri_3"],description:"Split into 3 smaller triangles"},{name:"center_split",fragments:["tri_main","tri_small"],description:"Center line split"}],circle:[{name:"half_circles",fragments:["semi_1","semi_2"],description:"Split into 2 semicircles"},{name:"pie_slices",fragments:["pie_1","pie_2","pie_3","pie_4"],description:"Quarter into 4 pie slices"}]}},a.createRoom("pre_op_prep",{size:[16,4,12],lighting:"clinical",position:[0,0,0],buildFunction:r,objectives:[{id:"patient_assessment",name:"Review Patient Chart",description:"Click on the Patient Chart to review fracture details and medical history",type:"simple",autoStart:!0,rewards:{experience:40}},{id:"surgical_prep",name:"Complete Pre-Op Preparation",description:"Use the 4 preparation stations: Handwash Station, Sterilization Unit, Surgical Gowns, and Pre-Op Checklist",type:"counter",target:4,progress:0,rewards:{experience:60,items:[{id:"surgical_clearance",quantity:1}]}},{id:"proceed_to_or",name:"Proceed to Operating Room",description:"All preparation complete! Use the door to enter the OR Suite and begin surgery",type:"guidance",prerequisites:["surgical_prep"],rewards:{experience:10}}]}),a.createRoom("or_suite",{size:[24,5,18],lighting:"surgical",position:[0,0,0],buildFunction:n,objectives:[{id:"fracture_exposure",name:"Expose the Fracture Site",description:"Use surgical tools to expose fracture: Click Scalpel Tray, then Retractor Set, then Hemostat Clamps",type:"counter",target:3,progress:0,rewards:{experience:100}},{id:"fracture_reduction",name:"Reduce the Fracture",description:"Align bone fragments using Reduction Clamps, Traction Device, and Alignment Guide to achieve 85% alignment",type:"counter",target:85,progress:0,rewards:{experience:200,skillPoints:3}},{id:"internal_fixation",name:"Apply Internal Fixation",description:"Stabilize fracture by clicking: Fixation Plate, then all 4 Screws, then Cerclage Wire (6 items total)",type:"counter",target:6,progress:0,rewards:{experience:150}},{id:"proceed_to_imaging",name:"Proceed to Imaging Suite",description:"Surgery complete! Use the door to enter the Fluoroscopy Suite for X-ray verification",type:"guidance",prerequisites:["internal_fixation"],rewards:{experience:10}}]}),a.createRoom("fluoroscopy_suite",{size:[14,4,16],lighting:"imaging",position:[0,0,0],buildFunction:c,objectives:[{id:"imaging_verification",name:"Take X-Ray Images",description:"Capture 3 imaging angles: Click AP View, Lateral View, and Oblique View buttons",type:"counter",target:3,progress:0,rewards:{experience:80}},{id:"hardware_positioning",name:"Verify Hardware Placement",description:"Click Hardware Check station to confirm all screws and plates are properly positioned",type:"simple",rewards:{experience:70}},{id:"proceed_to_recovery",name:"Proceed to Recovery Room",description:"Imaging verified! Use the door to enter Post-Op Recovery for surgical closure",type:"guidance",prerequisites:["hardware_positioning"],rewards:{experience:10}}]}),a.createRoom("post_op_recovery",{size:[12,4,10],lighting:"recovery",position:[0,0,0],buildFunction:s,objectives:[{id:"closure_completion",name:"Close the Surgical Site",description:"Suture in layers: Click Deep Sutures, then Subcutaneous Sutures, then Skin Closure",type:"counter",target:3,progress:0,rewards:{experience:60}},{id:"post_op_xray",name:"Take Final X-Ray",description:"Click Post-Op Imaging station to document final results and complete surgery",type:"simple",rewards:{experience:40,items:[{id:"surgical_report",quantity:1}]}},{id:"surgery_complete",name:"Surgery Successfully Completed",description:"Congratulations! The fracture reduction surgery is complete. You may continue practicing or explore other areas",type:"guidance",prerequisites:["post_op_xray"],rewards:{experience:25}}]}),a.createRoom("student_practice",{size:[16,4,14],lighting:"bright",position:[0,0,0],buildFunction:l,objectives:[{id:"learn_shapes",name:"Select a Shape to Study",description:"Click on one of the geometric shapes: Square, Triangle, or Circle to begin learning",type:"simple",autoStart:!0,rewards:{experience:25}},{id:"fracture_practice",name:"Practice Fracture Patterns",description:"Try 3 different fracture methods using the colored pattern stations around the room",type:"counter",target:3,progress:0,rewards:{experience:50}},{id:"reassembly_challenge",name:"Reassemble Broken Shapes",description:"Click on the colored Fragment pieces to reconstruct fractured shapes (complete 5 assemblies)",type:"counter",target:5,progress:0,rewards:{experience:75,skillPoints:1}},{id:"continue_practice",name:"Continue Practicing",description:"Great work! Use Random Fracture Generator for new challenges or Reset Puzzle to try again. Return to Pre-Op when ready for medical training",type:"guidance",prerequisites:["reassembly_challenge"],rewards:{experience:15}}]}),a.createDoor("pre_op_prep","or_suite",{type:"objective",id:"surgical_prep"},{playerSpawnPosition:[-10,0,0]}),a.createDoor("pre_op_prep","student_practice",{type:"none"},{playerSpawnPosition:[0,0,-6]}),a.createDoor("or_suite","fluoroscopy_suite",{type:"objective",id:"fracture_reduction"},{playerSpawnPosition:[6,0,0]}),a.createDoor("fluoroscopy_suite","post_op_recovery",{type:"objective",id:"imaging_verification"},{playerSpawnPosition:[0,0,4]}),a.createDoor("or_suite","fluoroscopy_suite",{type:"none"},{playerSpawnPosition:[8,0,-6]});const p=await a.build(e,t,i);return p.multiRoom=a,p.fractureData=this.fractureData,p},onLoad(e,t){console.log("[FractureReduction] Orthopedic surgery simulation initiated...");const i=e.root.findByTag("scene_root")[0];i&&i.multiRoom&&(i.multiRoom.onLoad(e,t),this.multiRoom=i.multiRoom,this.fractureData=i.fractureData,this.interactionHandler=i=>{this.handleSurgicalInteraction(i,e,t)},this.multiRoom.setSceneInteractionHandler(this.interactionHandler),this.initializeFractureSimulation()),e.fire("ui:notification",{text:"TRAUMA ALERT: Complex fracture requires immediate reduction and fixation",type:"warning",duration:5e3}),this.surgicalStartTime=Date.now(),this.updateSurgicalTimer(e)},initializeFractureSimulation(){this.fractureData.fragmentPositions=[{id:"proximal_fragment",displacement:[0,0,15],angulation:[12,0,-8]},{id:"distal_fragment",displacement:[0,0,-18],angulation:[-15,0,12]},{id:"butterfly_fragment",displacement:[8,0,0],angulation:[0,25,0]}],this.fractureData.originalAlignment={displacement:[0,0,0],angulation:[0,0,0],rotation:[0,0,0]},this.fractureData.currentAlignment={displacement:[0,0,33],angulation:[27,0,4],rotation:[0,25,0]},console.log("[FractureReduction] Fracture simulation initialized - Complex comminuted pattern")},updateSurgicalTimer(e){this.surgicalStartTime&&(this.fractureData.surgicalTime=Math.floor((Date.now()-this.surgicalStartTime)/1e3),this.fractureData.surgicalTime>180&&(this.fractureData.patientVitals.stable=!1,this.fractureData.patientVitals.painLevel=Math.min(10,7+Math.floor(this.fractureData.surgicalTime/60))),setTimeout(()=>this.updateSurgicalTimer(e),1e3))},checkGuidanceObjectives(e,t){this.multiRoom&&this.multiRoom.currentRoom&&setTimeout(()=>{this.multiRoom.checkAndActivateGuidanceObjectives(this.multiRoom.currentRoom)},50)},handleSurgicalInteraction(e,t,i){console.log("[FractureReduction] Surgical interaction:",e);const o=i.getSystem("objectivemanager"),a=this.multiRoom.currentRoom;if("PatientChart"===e&&"pre_op_prep"===a)o.isObjectiveActive("patient_assessment")&&(o.completeObjective("patient_assessment"),o.startObjective("surgical_prep"),t.fire("ui:notification",{text:"Chart Review: 45-year-old male, closed comminuted femur fracture from MVA",type:"info",duration:4e3}),this.checkGuidanceObjectives(t,i));else if(["HandwashStation","SterilizationUnit","SurgicalGowns","PreOpChecklist"].includes(e)){if(o.isObjectiveActive("surgical_prep")){const a={HandwashStation:"Surgical hand scrub completed - 5 minutes",SterilizationUnit:"Instruments sterilized and ready",SurgicalGowns:"Sterile gowning and gloving completed",PreOpChecklist:"WHO surgical safety checklist verified"};t.fire("ui:notification",{text:a[e],type:"success",duration:2500});const r=o.objectives.get("surgical_prep")?.progress||0;o.updateObjective("surgical_prep",r+1),o.isComplete("surgical_prep")&&(this.multiRoom.addItem("surgical_clearance"),t.fire("ui:notification",{text:"PRE-OP COMPLETE: Patient ready for surgical intervention",type:"success",duration:3500}),this.checkGuidanceObjectives(t,i))}}else if(["ScalpelTray","RetractorSet","HemostatClamps"].includes(e)){if(o.isObjectiveActive("fracture_exposure")){const a={ScalpelTray:"incision_planning",RetractorSet:"tissue_dissection",HemostatClamps:"fracture_visualization"}[e],r={incision_planning:"Lateral approach planned - minimally invasive technique",tissue_dissection:"Careful dissection preserving soft tissue envelope",fracture_visualization:"Fracture site exposed - comminuted pattern confirmed"};t.fire("ui:notification",{text:r[a],type:"info",duration:3e3});const n=o.objectives.get("fracture_exposure")?.progress||0;o.updateObjective("fracture_exposure",n+1),o.isComplete("fracture_exposure")&&(o.startObjective("fracture_reduction"),t.fire("ui:notification",{text:"EXPOSURE COMPLETE: Begin fracture reduction maneuvers",type:"warning",duration:3500}),this.checkGuidanceObjectives(t,i))}}else if(["ReductionClamps","TractionDevice","AlignmentGuide"].includes(e))o.isObjectiveActive("fracture_reduction")&&this.performFractureReduction(e,t,o);else if(e.startsWith("FixationHardware_")){if(o.isObjectiveActive("internal_fixation")){const a=e.split("_")[1],r={Plate:"Locking compression plate applied to lateral cortex",Screw1:"Proximal locking screw - bicortical purchase achieved",Screw2:"Distal locking screw - optimal thread engagement",Screw3:"Lag screw through butterfly fragment - compression achieved",Screw4:"Additional cortical screw for rotational stability",Wire:"Cerclage wire for additional fragment control"};t.fire("ui:notification",{text:r[a]||"Fixation hardware applied",type:"success",duration:2500});const n=o.objectives.get("internal_fixation")?.progress||0;o.updateObjective("internal_fixation",n+1),o.isComplete("internal_fixation")&&(t.fire("ui:notification",{text:"FIXATION COMPLETE: Proceed to fluoroscopic verification",type:"success",duration:4e3}),this.checkGuidanceObjectives(t,i))}}else if(["FluoroscopyUnit","ImagingAngle_AP","ImagingAngle_Lateral","ImagingAngle_Oblique"].includes(e))o.isObjectiveActive("imaging_verification")&&this.performFluoroscopyImaging(e,t,o);else if("HardwareCheck"===e){if(o.isObjectiveActive("hardware_positioning")){const e=this.calculateReductionQuality();e>=85?(o.completeObjective("hardware_positioning"),o.startObjective("closure_completion"),t.fire("ui:notification",{text:`EXCELLENT REDUCTION: ${e}% anatomical alignment achieved`,type:"success",duration:4e3}),this.checkGuidanceObjectives(t,i)):t.fire("ui:notification",{text:`SUBOPTIMAL REDUCTION: ${e}% - Consider revision`,type:"warning",duration:3500})}}else if(["DeepSutures","SubcutaneousSutures","SkinClosure"].includes(e)){if(o.isObjectiveActive("closure_completion")){const a={DeepSutures:"deep_closure",SubcutaneousSutures:"subcutaneous_closure",SkinClosure:"skin_closure"}[e],r={deep_closure:"Deep fascial closure with absorbable sutures",subcutaneous_closure:"Subcutaneous layer closed - dead space eliminated",skin_closure:"Skin closure with interrupted sutures - excellent approximation"};t.fire("ui:notification",{text:r[a],type:"info",duration:2500});const n=o.objectives.get("closure_completion")?.progress||0;o.updateObjective("closure_completion",n+1),o.isComplete("closure_completion")&&(o.startObjective("post_op_xray"),this.checkGuidanceObjectives(t,i))}}else if(["GeometricSquare","GeometricTriangle","GeometricCircle"].includes(e)){if(o.isObjectiveActive("learn_shapes")&&"student_practice"===a){const a={GeometricSquare:"square",GeometricTriangle:"triangle",GeometricCircle:"circle"};this.geometricData.currentShape=a[e],o.completeObjective("learn_shapes"),o.startObjective("fracture_practice"),t.fire("ui:notification",{text:`Selected ${this.geometricData.currentShape.toUpperCase()} for geometric fracture study`,type:"info",duration:3e3}),this.checkGuidanceObjectives(t,i)}}else if(e.startsWith("GeometricPattern_")){if(o.isObjectiveActive("fracture_practice")&&"student_practice"===a){const i=e.split("_")[1];this.applyGeometricPattern(i,t,o)}}else if(e.startsWith("GeometricFragment_"))o.isObjectiveActive("reassembly_challenge")&&"student_practice"===a&&this.manipulateGeometricFragment(e,t,o);else if("RandomGeometricFracture"===e)"student_practice"===a&&this.generateRandomGeometricFracture(t);else if("ResetGeometricPuzzle"===e)"student_practice"===a&&this.resetGeometricPuzzle(t);else if("PostOpImaging"===e&&o.isObjectiveActive("post_op_xray")){this.multiRoom.addItem("surgical_report"),o.completeObjective("post_op_xray");const e=Math.floor((Date.now()-this.surgicalStartTime)/1e3/60),a=this.calculateReductionQuality();t.fire("ui:notification",{text:`SURGERY COMPLETE: ${e}min duration, ${a}% reduction quality`,type:"success",duration:6e3}),this.checkGuidanceObjectives(t,i)}},performFractureReduction(e,t,i){const o={ReductionClamps:{displacement:8,angulation:12,difficulty:"moderate"},TractionDevice:{displacement:15,angulation:8,difficulty:"high"},AlignmentGuide:{displacement:5,angulation:20,difficulty:"precision"}}[e];if(!o)return;this.fractureData.currentAlignment.displacement[2]-=o.displacement,this.fractureData.currentAlignment.angulation[0]-=o.angulation,this.fractureData.currentAlignment.displacement[2]=Math.max(0,this.fractureData.currentAlignment.displacement[2]),this.fractureData.currentAlignment.angulation[0]=Math.max(0,this.fractureData.currentAlignment.angulation[0]);const a=this.calculateReductionQuality(),r=i.objectives.get("fracture_reduction")?.progress||0;i.updateObjective("fracture_reduction",r+1),t.fire("ui:notification",{text:`${{ReductionClamps:"Reduction clamps applied - gradual distraction and alignment",TractionDevice:"Traction applied - length and axis restoration",AlignmentGuide:"Precise alignment guide - fine-tuning reduction"}[e]} - Reduction: ${a}%`,type:a>=85?"success":"info",duration:3e3}),a>=85&&(i.completeObjective("fracture_reduction"),i.startObjective("internal_fixation"),t.fire("ui:notification",{text:"ANATOMICAL REDUCTION ACHIEVED: Proceed with internal fixation",type:"success",duration:4e3}),this.checkGuidanceObjectives(t,core))},performFluoroscopyImaging(e,t,i){this.fractureData.fluoroscopyImages++,t.fire("ui:notification",{text:{FluoroscopyUnit:"Fluoroscopy unit positioned - C-arm alignment optimal",ImagingAngle_AP:"AP view acquired - anterior-posterior alignment verified",ImagingAngle_Lateral:"Lateral view acquired - sagittal plane assessment",ImagingAngle_Oblique:"Oblique view acquired - rotational alignment confirmed"}[e]||"Fluoroscopic image acquired",type:"info",duration:2500});const o=i.objectives.get("imaging_verification")?.progress||0;i.updateObjective("imaging_verification",o+1),i.isComplete("imaging_verification")&&(i.startObjective("hardware_positioning"),t.fire("ui:notification",{text:`IMAGING COMPLETE: ${this.fractureData.fluoroscopyImages} views acquired`,type:"success",duration:3e3}),this.checkGuidanceObjectives(t,core))},calculateReductionQuality(){const e=Math.abs(this.fractureData.currentAlignment.displacement[2]),t=Math.abs(this.fractureData.currentAlignment.angulation[0]),i=Math.max(0,100-3*e),o=Math.max(0,100-4*t),a=Math.floor((i+o)/2);return this.fractureData.reductionQuality=a,a},applyGeometricPattern(e,t,i){const o=this.geometricData.currentShape,a=this.geometricData.fracturePatterns[o];if(!a)return;const r=a.find(t=>t.name===e);if(!r)return;this.geometricData.selectedPattern=r,this.geometricData.fragments=[...r.fragments],this.geometricData.practiceAttempts++;const n=i.objectives.get("fracture_practice")?.progress||0;i.updateObjective("fracture_practice",n+1),t.fire("ui:notification",{text:`${o.toUpperCase()} fractured using ${e}: ${r.description}`,type:"success",duration:4e3}),i.isComplete("fracture_practice")&&(i.startObjective("reassembly_challenge"),t.fire("ui:notification",{text:"FRACTURE PRACTICE COMPLETE! Now try reassembly challenges",type:"success",duration:3500}),this.checkGuidanceObjectives(t,core)),console.log("[GeometricFracture] Applied pattern:",e,"Fragments:",r.fragments.length)},manipulateGeometricFragment(e,t,i){if(!this.geometricData.selectedPattern)return void t.fire("ui:notification",{text:"Select a shape and fracture pattern first!",type:"warning",duration:2500});const o=e.split("_")[1];this.geometricData.assemblyProgress+=100/this.geometricData.fragments.length,this.geometricData.assemblyProgress=Math.min(100,this.geometricData.assemblyProgress);const a=i.objectives.get("reassembly_challenge")?.progress||0;i.updateObjective("reassembly_challenge",a+1),t.fire("ui:notification",{text:`Fragment ${o} positioned - Assembly: ${Math.floor(this.geometricData.assemblyProgress)}%`,type:this.geometricData.assemblyProgress>=100?"success":"info",duration:2500}),this.geometricData.assemblyProgress>=100&&(t.fire("ui:notification",{text:`PERFECT RECONSTRUCTION! ${this.geometricData.currentShape.toUpperCase()} successfully reassembled`,type:"success",duration:4e3}),i.isComplete("reassembly_challenge")&&this.checkGuidanceObjectives(t,core),setTimeout(()=>{this.resetGeometricPuzzle(t,!1)},2e3))},generateRandomGeometricFracture(e){const t=["square","triangle","circle"],i=t[Math.floor(Math.random()*t.length)];this.geometricData.currentShape=i;const o=this.geometricData.fracturePatterns[i],a=o[Math.floor(Math.random()*o.length)];this.geometricData.selectedPattern=a,this.geometricData.fragments=[...a.fragments],this.geometricData.assemblyProgress=0,e.fire("ui:notification",{text:`RANDOM CHALLENGE: ${i.toUpperCase()} → ${a.name} (${a.fragments.length} pieces)`,type:"warning",duration:4e3})},resetGeometricPuzzle(e,t=!0){this.geometricData.currentShape="square",this.geometricData.selectedPattern=null,this.geometricData.fragments=[],this.geometricData.assemblyProgress=0,t&&e.fire("ui:notification",{text:"Geometric puzzle reset - Ready for new shape fracture challenge",type:"info",duration:3e3})},onUnload(e,t){console.log("[FractureReduction] Surgical simulation concluded"),this.multiRoom&&this.multiRoom.setSceneInteractionHandler(null),this.interactionHandler=null,this.multiRoom&&this.multiRoom.onUnload(e,t),this.surgicalStartTime=null}};async function r(e,t,i,o){console.log("[FractureReduction] Building pre-operative preparation room...");const a=i.create("PatientChart",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[.5,.3,.1]},rigidbody:{type:"static"}},position:[-6,1.5,-4],scale:[1,.6,.2],tags:["interactive","chart"]});if(a.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(1,.9,.8),e.update(),a.model.meshInstances.forEach(t=>t.material=e)}o.addEntityToRoom(a,"pre_op_prep");const r=i.create("XRayViewer",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[1,1.2,.1]}},position:[-6,1.2,-5],scale:[2,2.4,.2],tags:["medical_equipment"]});if(r.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.9,.9,.9),e.emissive=new pc.Color(.3,.3,.4),e.update(),r.model.meshInstances.forEach(t=>t.material=e)}e.addChild(r),[{name:"HandwashStation",pos:[6,1,-4],scale:[1.5,2,.8],color:[.8,.9,1]},{name:"SterilizationUnit",pos:[6,1.2,0],scale:[2,2.4,1.2],color:[.9,.9,.9]},{name:"SurgicalGowns",pos:[4,1.8,4],scale:[1,1.6,.5],color:[.7,.8,.9]},{name:"PreOpChecklist",pos:[0,1,4],scale:[.8,.4,.1],color:[1,1,.9]}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[e.scale[0]/2,e.scale[1]/2,e.scale[2]/2]},rigidbody:{type:"static"}},position:e.pos,scale:e.scale,tags:["interactive","prep_station"]});if(t.model){const i=new pc.StandardMaterial;i.diffuse=new pc.Color(e.color[0],e.color[1],e.color[2]),i.update(),t.model.meshInstances.forEach(e=>e.material=i)}o.addEntityToRoom(t,"pre_op_prep")}),[{pos:[0,3.5,0],color:new pc.Color(.95,.95,1)},{pos:[-4,3,-3],color:new pc.Color(.9,.9,1)},{pos:[4,3,3],color:new pc.Color(.9,.9,1)}].forEach(t=>{const o=i.createLight("point",{color:t.color,intensity:2.2,range:12,position:t.pos});e.addChild(o)})}async function n(e,t,i,o){console.log("[FractureReduction] Building operating room suite...");const a=i.create("OperatingTable",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[3,.8,1]},rigidbody:{type:"static"}},position:[0,.8,0],scale:[6,1.6,2],tags:["surgical_table"]});if(a.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.9,.9,.9),e.metalness=.3,e.update(),a.model.meshInstances.forEach(t=>t.material=e)}e.addChild(a);const r=i.create("Patient",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[2.5,.3,.8]}},position:[0,1.9,0],scale:[5,.6,1.6],tags:["patient"]});if(r.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.7,.8,.9),e.update(),r.model.meshInstances.forEach(t=>t.material=e)}e.addChild(r),[{name:"ScalpelTray",pos:[-8,1.2,-2],scale:[1.5,.3,1],color:[.8,.8,.9]},{name:"RetractorSet",pos:[-8,1.2,2],scale:[1.5,.3,1.2],color:[.7,.8,.8]},{name:"HemostatClamps",pos:[-6,1.2,-6],scale:[1,.3,.8],color:[.9,.8,.7]}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[e.scale[0]/2,e.scale[1]/2,e.scale[2]/2]},rigidbody:{type:"static"}},position:e.pos,scale:e.scale,tags:["interactive","surgical_instrument"]});if(t.model){const i=new pc.StandardMaterial;i.diffuse=new pc.Color(e.color[0],e.color[1],e.color[2]),i.metalness=.6,i.update(),t.model.meshInstances.forEach(e=>e.material=i)}o.addEntityToRoom(t,"or_suite")}),[{name:"ReductionClamps",pos:[8,1.2,-4],scale:[1.2,.6,.4],color:[.6,.7,.8]},{name:"TractionDevice",pos:[8,1.5,0],scale:[1,2,.8],color:[.7,.6,.8]},{name:"AlignmentGuide",pos:[8,1.2,4],scale:[.8,.8,1.2],color:[.8,.7,.6]}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[e.scale[0]/2,e.scale[1]/2,e.scale[2]/2]},rigidbody:{type:"static"}},position:e.pos,scale:e.scale,tags:["interactive","reduction_tool"]});if(t.model){const i=new pc.StandardMaterial;i.diffuse=new pc.Color(e.color[0],e.color[1],e.color[2]),i.metalness=.7,i.update(),t.model.meshInstances.forEach(e=>e.material=i)}o.addEntityToRoom(t,"or_suite")}),[{name:"FixationHardware_Plate",pos:[6,1.2,-8],scale:[1.5,.2,.3],color:[.9,.9,.95]},{name:"FixationHardware_Screw1",pos:[4,1.2,-8],scale:[.3,.2,.3],color:[.95,.95,1]},{name:"FixationHardware_Screw2",pos:[2,1.2,-8],scale:[.3,.2,.3],color:[.95,.95,1]},{name:"FixationHardware_Screw3",pos:[0,1.2,-8],scale:[.3,.2,.3],color:[.95,.95,1]},{name:"FixationHardware_Screw4",pos:[-2,1.2,-8],scale:[.3,.2,.3],color:[.95,.95,1]},{name:"FixationHardware_Wire",pos:[-4,1.2,-8],scale:[.2,.1,.8],color:[.8,.9,.9]}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[e.scale[0]/2,e.scale[1]/2,e.scale[2]/2]},rigidbody:{type:"static"}},position:e.pos,scale:e.scale,tags:["interactive","fixation_hardware"]});if(t.model){const i=new pc.StandardMaterial;i.diffuse=new pc.Color(e.color[0],e.color[1],e.color[2]),i.metalness=.9,i.update(),t.model.meshInstances.forEach(e=>e.material=i)}o.addEntityToRoom(t,"or_suite")}),[{pos:[0,4.8,0],color:new pc.Color(1,1,1)},{pos:[-3,4.5,0],color:new pc.Color(.98,.98,1)},{pos:[3,4.5,0],color:new pc.Color(.98,.98,1)},{pos:[0,4.5,-3],color:new pc.Color(.95,.95,1)},{pos:[0,4.5,3],color:new pc.Color(.95,.95,1)}].forEach(t=>{const o=i.createLight("point",{color:t.color,intensity:2.8,range:15,position:t.pos});e.addChild(o)})}async function c(e,t,i,o){console.log("[FractureReduction] Building fluoroscopy imaging suite...");const a=i.create("FluoroscopyUnit",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[2,3,2]},rigidbody:{type:"static"}},position:[0,3,0],scale:[4,6,4],tags:["interactive","imaging_equipment"]});if(a.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.2,.2,.2),e.emissive=new pc.Color(0,.1,.2),e.metalness=.8,e.update(),a.model.meshInstances.forEach(t=>t.material=e)}o.addEntityToRoom(a,"fluoroscopy_suite");const r=i.create("ImagingControl",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[1.5,1.2,.8]}},position:[-5,1.2,-6],scale:[3,2.4,1.6],tags:["imaging_control"]});if(r.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.3,.3,.3),e.emissive=new pc.Color(.1,.1,0),e.update(),r.model.meshInstances.forEach(t=>t.material=e)}e.addChild(r),[{name:"ImagingAngle_AP",pos:[5,1.2,-4],label:"AP View"},{name:"ImagingAngle_Lateral",pos:[5,1.2,0],label:"Lateral View"},{name:"ImagingAngle_Oblique",pos:[5,1.2,4],label:"Oblique View"}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[.8,.8,.4]},rigidbody:{type:"static"}},position:e.pos,scale:[1.6,1.6,.8],tags:["interactive","imaging_angle"]});if(t.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.1,.3,.6),e.emissive=new pc.Color(0,.1,.2),e.update(),t.model.meshInstances.forEach(t=>t.material=e)}o.addEntityToRoom(t,"fluoroscopy_suite")});const n=i.create("HardwareCheck",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[1,.8,.6]},rigidbody:{type:"static"}},position:[0,.8,6],scale:[2,1.6,1.2],tags:["interactive","verification"]});if(n.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.2,.6,.3),e.emissive=new pc.Color(.1,.2,.1),e.update(),n.model.meshInstances.forEach(t=>t.material=e)}o.addEntityToRoom(n,"fluoroscopy_suite"),[{pos:[0,3.5,-6],color:new pc.Color(.6,.7,.8)},{pos:[-6,3,0],color:new pc.Color(.5,.6,.7)},{pos:[6,3,0],color:new pc.Color(.5,.6,.7)}].forEach(t=>{const o=i.createLight("point",{color:t.color,intensity:1.5,range:10,position:t.pos});e.addChild(o)})}async function s(e,t,i,o){console.log("[FractureReduction] Building post-operative recovery room...");const a=i.create("ClosureStation",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[1.5,.8,1]}},position:[0,.8,-2],scale:[3,1.6,2],tags:["surgical_station"]});if(a.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.9,.9,.9),e.update(),a.model.meshInstances.forEach(t=>t.material=e)}e.addChild(a),[{name:"DeepSutures",pos:[-3,1.2,-2],scale:[.6,.3,.4],color:[.7,.8,.9]},{name:"SubcutaneousSutures",pos:[0,1.2,-2],scale:[.6,.3,.4],color:[.8,.7,.9]},{name:"SkinClosure",pos:[3,1.2,-2],scale:[.6,.3,.4],color:[.9,.8,.7]}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[e.scale[0]/2,e.scale[1]/2,e.scale[2]/2]},rigidbody:{type:"static"}},position:e.pos,scale:e.scale,tags:["interactive","suture_material"]});if(t.model){const i=new pc.StandardMaterial;i.diffuse=new pc.Color(e.color[0],e.color[1],e.color[2]),i.update(),t.model.meshInstances.forEach(e=>e.material=i)}o.addEntityToRoom(t,"post_op_recovery")});const r=i.create("PostOpImaging",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[2,1.5,1]},rigidbody:{type:"static"}},position:[0,1.5,3],scale:[4,3,2],tags:["interactive","post_op_imaging"]});if(r.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.2,.3,.4),e.emissive=new pc.Color(.1,.15,.2),e.update(),r.model.meshInstances.forEach(t=>t.material=e)}o.addEntityToRoom(r,"post_op_recovery"),[{name:"PatientMonitor",pos:[-4,1.5,0],scale:[1.2,1.8,.4],color:[.2,.2,.3]},{name:"VitalSigns",pos:[4,1.2,0],scale:[1,1.4,.6],color:[.3,.4,.2]}].forEach(t=>{const o=i.create(t.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[t.scale[0]/2,t.scale[1]/2,t.scale[2]/2]}},position:t.pos,scale:t.scale,tags:["monitoring_equipment"]});if(o.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(t.color[0],t.color[1],t.color[2]),e.emissive=new pc.Color(0,.1,0),e.update(),o.model.meshInstances.forEach(t=>t.material=e)}e.addChild(o)}),[{pos:[0,3.5,0],color:new pc.Color(.9,.85,.8)},{pos:[-3,3,2],color:new pc.Color(.85,.9,.8)},{pos:[3,3,-2],color:new pc.Color(.8,.85,.9)}].forEach(t=>{const o=i.createLight("point",{color:t.color,intensity:1.8,range:8,position:t.pos});e.addChild(o)})}async function l(e,t,i,o){console.log("[FractureReduction] Building student practice room for geometric fracture mechanics...");const a=i.create("LearningTable",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[3,.6,2]}},position:[0,.6,0],scale:[6,1.2,4],tags:["learning_equipment"]});if(a.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.8,.7,.6),e.update(),a.model.meshInstances.forEach(t=>t.material=e)}e.addChild(a),[{name:"GeometricSquare",pos:[-4,1.5,-4],shape:"box",scale:[2,.2,2],color:[.8,.2,.2]},{name:"GeometricTriangle",pos:[0,1.5,-4],shape:"cone",scale:[2,2,2],color:[.2,.8,.2]},{name:"GeometricCircle",pos:[4,1.5,-4],shape:"sphere",scale:[1,1,1],color:[.2,.2,.8]}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:e.shape},collision:{type:"box",halfExtents:[1,1,1]},rigidbody:{type:"static"}},position:e.pos,scale:e.scale,tags:["interactive","geometric_shape"]});if(t.model){const i=new pc.StandardMaterial;i.diffuse=new pc.Color(e.color[0],e.color[1],e.color[2]),i.emissive=new pc.Color(.2*e.color[0],.2*e.color[1],.2*e.color[2]),i.update(),t.model.meshInstances.forEach(e=>e.material=i)}o.addEntityToRoom(t,"student_practice")}),[{name:"GeometricPattern_rectangles",pos:[-6,1.2,0],label:"Rectangle\nSplit",color:[.9,.6,.2]},{name:"GeometricPattern_triangles",pos:[-6,1.2,2],label:"Triangle\nBreak",color:[.6,.9,.2]},{name:"GeometricPattern_mini_squares",pos:[6,1.2,0],label:"Mini\nSquares",color:[.2,.9,.6]},{name:"GeometricPattern_center_circle",pos:[6,1.2,2],label:"Center\nCircle",color:[.9,.2,.6]},{name:"GeometricPattern_half_circles",pos:[-6,1.2,-2],label:"Half\nCircles",color:[.6,.2,.9]},{name:"GeometricPattern_pie_slices",pos:[6,1.2,-2],label:"Pie\nSlices",color:[.9,.9,.2]}].forEach(e=>{const t=i.create(e.name,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[1,.6,.8]},rigidbody:{type:"static"}},position:e.pos,scale:[2,1.2,1.6],tags:["interactive","geometric_pattern"]});if(t.model){const i=new pc.StandardMaterial;i.diffuse=new pc.Color(e.color[0],e.color[1],e.color[2]),i.emissive=new pc.Color(.3*e.color[0],.3*e.color[1],.3*e.color[2]),i.update(),t.model.meshInstances.forEach(e=>e.material=i)}o.addEntityToRoom(t,"student_practice")}),[[-2,1,4],[-1,1,4],[0,1,4],[1,1,4],[2,1,4],[-2,1,5],[-1,1,5],[0,1,5],[1,1,5],[2,1,5]].forEach((e,t)=>{const a=i.create(`GeometricFragment_${t}`,{components:{model:{type:"box"},collision:{type:"box",halfExtents:[.4,.3,.4]},rigidbody:{type:"static"}},position:e,scale:[.8,.6,.8],tags:["interactive","geometric_fragment"]});if(a.model){const e=[[1,.2,.2],[.2,1,.2],[.2,.2,1],[1,1,.2],[1,.2,1],[.2,1,1],[1,.6,.2],[.6,.2,1],[.2,1,.6],[1,.2,.6]],i=t%e.length,[o,r,n]=e[i],c=new pc.StandardMaterial;c.diffuse=new pc.Color(o,r,n),c.emissive=new pc.Color(.2*o,.2*r,.2*n),c.update(),a.model.meshInstances.forEach(e=>e.material=c)}o.addEntityToRoom(a,"student_practice")});const r=i.create("RandomGeometricFracture",{components:{model:{type:"box"},collision:{type:"box",halfExtents:[1.5,1,.5]},rigidbody:{type:"static"}},position:[0,1,-6],scale:[3,2,1],tags:["interactive","random_generator"]});if(r.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(1,.5,0),e.emissive=new pc.Color(.3,.15,0),e.emissiveIntensity=.5,e.update(),r.model.meshInstances.forEach(t=>t.material=e)}o.addEntityToRoom(r,"student_practice");const n=i.create("ResetGeometricPuzzle",{components:{model:{type:"sphere"},collision:{type:"sphere",radius:1},rigidbody:{type:"static"}},position:[0,1,6],scale:[2,2,2],tags:["interactive","reset_button"]});if(n.model){const e=new pc.StandardMaterial;e.diffuse=new pc.Color(.7,.7,.7),e.emissive=new pc.Color(.2,.2,.2),e.metalness=.8,e.update(),n.model.meshInstances.forEach(t=>t.material=e)}o.addEntityToRoom(n,"student_practice"),[{pos:[0,3.5,0],color:new pc.Color(1,1,1)},{pos:[-4,3,-4],color:new pc.Color(.95,.95,1)},{pos:[4,3,-4],color:new pc.Color(.95,.95,1)},{pos:[0,3,4],color:new pc.Color(1,.95,.9)},{pos:[0,3,-6],color:new pc.Color(1,.9,.8)}].forEach(t=>{const o=i.createLight("point",{color:t.color,intensity:2.2,range:10,position:t.pos});e.addChild(o)})}}}]);