DIRECTORY BasicTime, CubicSplines, FS, GGAlign, GGCaret, GGDescribe, GGDrawProcess, GGError, GGEvent, GGGravity, GGInterfaceTypes, GGModelTypes, GGObjects, GGRefresh, GGSegment, GGSelect, GGTouch, GGVector, GGWindow, Imager, ImagerInterpress, IO, Random, Real, Rope, Rosary, ViewerClasses, ViewerIO, ViewerOps, ViewerTools; GGEventImplA: CEDAR PROGRAM IMPORTS BasicTime, FS, GGAlign, GGCaret, GGDescribe, GGDrawProcess, GGError, GGGravity, GGObjects, GGRefresh, GGSegment, GGSelect, GGTouch, GGVector, GGWindow, Imager, ImagerInterpress, IO, Random, Real, Rope, Rosary, ViewerIO, ViewerOps, ViewerTools EXPORTS GGEvent = BEGIN Cluster: TYPE = GGModelTypes.Cluster; EntityGenerator: TYPE = GGModelTypes.EntityGenerator; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; Outline: TYPE = GGModelTypes.Outline; Point: TYPE = GGModelTypes.Point; ScalarButtonClient: TYPE = GGInterfaceTypes.ScalarButtonClient; Segment: TYPE = GGModelTypes.Segment; Sequence: TYPE = GGModelTypes.Sequence; Traj: TYPE = GGModelTypes.Traj; TrajGenerator: TYPE = GGModelTypes.TrajGenerator; TwoState: TYPE = GGInterfaceTypes.TwoState; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; SequenceGenerator: TYPE = GGModelTypes.SequenceGenerator; Vector: TYPE = GGModelTypes.Vector; Viewer: TYPE = ViewerClasses.Viewer; Clear: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Reset: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Get: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Store: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Split: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Interpress: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { ipRef: ImagerInterpress.Ref; wdir, ipName, fullName: Rope.ROPE; success: BOOL; pixelsPerMeter: REAL _ 0.0254 / 72.0; startTime: BasicTime.GMT; endTime: BasicTime.GMT; totalTime: INT; msgRope: Rope.ROPE; DoMakeInterpress: PROC [dc: Imager.Context] = { Imager.ScaleT[dc, pixelsPerMeter]; GGRefresh.InterpressEntireScene[dc, gargoyleData]; }; ipName _ ViewerTools.GetSelectionContents[]; IF Rope.Length[ipName] = 0 THEN RETURN; wdir _ gargoyleData.originalWorkingDirectory; success _ TRUE; [fullName,,] _ FS.ExpandName[ipName, wdir ! FS.Error => IF error.group = user THEN { success _ FALSE; CONTINUE; } ]; IF NOT success THEN RETURN; ipRef _ ImagerInterpress.Create[fullName]; msgRope _ IO.PutFR["Writing to interpress file: %g . . . ", [rope[fullName]]]; GGError.Append[msgRope, begin]; startTime _ BasicTime.Now[]; ImagerInterpress.DoPage[ipRef, DoMakeInterpress, 1.0]; ImagerInterpress.Close[ipRef]; endTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[startTime, endTime]; msgRope _ IO.PutFR[" Done in time (%r)", [integer[totalTime]]]; GGError.Append[msgRope, end]; }; Delete: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { parentOutline: Outline; entityGen: EntityGenerator; entityGen _ GGSelect.SelectedEntities[gargoyleData, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO GGSelect.DeselectEntity[entity, gargoyleData, normal]; GGSelect.DeselectEntity[entity, gargoyleData, copy]; GGSelect.DeselectEntity[entity, gargoyleData, hot]; GGSelect.DeselectEntity[entity, gargoyleData, active]; WITH entity SELECT FROM cluster: Cluster => ERROR NotYetImplemented; outline: Outline => { GGObjects.DeleteOutline[gargoyleData.scene, outline]; GGTouch.OutlineDeleted[outline, gargoyleData]; }; seq: Sequence => { parentOutline _ GGObjects.OutlineOfTraj[seq.traj]; IF GGObjects.HasHoles[parentOutline] THEN { SELECT seq.traj.role FROM hole => ERROR NotYetImplemented; open => ERROR; -- impossible since the outline has holes fence => { GGError.Append["You can't delete the fence trajectory of an outline with holes.", oneLiner]; LOOP; }; ENDCASE => ERROR; } ELSE { IF seq.all THEN { -- the whole trajectory is selected GGObjects.DeleteOutline[gargoyleData.scene, parentOutline]; GGTouch.OutlineDeleted[parentOutline, gargoyleData]; } ELSE { -- part of a trajectory is selected. Remove the parts in a sensible fashion. This may require breaking up the trajectory into pieces. Remove all of the pieces from touching lists. IF seq.parts.rest # NIL OR (seq.parts.first.start # 0 AND seq.parts.first.end # GGObjects.HiJoint[seq.traj]) THEN { GGError.Append["Deleting parts of trajectories is not implemented.", oneLiner]; GGError.Blink[]; } ELSE { IF seq.traj.role = fence THEN seq.traj.role _ open; GGTouch.SequenceDeleted[seq, gargoyleData]; IF seq.parts.first.start = 0 THEN { seq.traj.joints _ Rosary.Substr[seq.traj.joints, seq.parts.first.end]; seq.traj.segments _ Rosary.Substr[seq.traj.segments, seq.parts.first.end]; seq.traj.segCount _ seq.traj.segCount - (seq.parts.first.end-seq.parts.first.start); } ELSE { seq.traj.joints _ Rosary.Substr[seq.traj.joints, 0, seq.parts.first.start + 1]; seq.traj.segments _ Rosary.Substr[seq.traj.segments, 0, seq.parts.first.start]; seq.traj.segCount _ seq.traj.segCount - (seq.parts.first.end-seq.parts.first.start); } }; }; }; }; ENDCASE => ERROR; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SelectAll: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGSelect.DeselectAll[gargoyleData, normal]; GGSelect.SelectAll[gargoyleData, normal]; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; NotYetImplemented: PUBLIC SIGNAL = CODE; SetStraight: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO newSeg _ GGSegment.MakeLine[next.seg.lo, next.seg.hi]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SetArc: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; p0, p1, p2: Point; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO p0 _ next.seg.lo; p2 _ next.seg.hi; p1 _ GetPt[p0, GGVector.Sub[p2,p0], GGVector.Distance[p0,p1]]; newSeg _ GGSegment.MakeArc[p0, p1, p2]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SetConic: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; p0, p1, p2: Point; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO p0 _ next.seg.lo; p2 _ next.seg.hi; p1 _ GetPt[p0, GGVector.Sub[p2,p0], GGVector.Distance[p0,p1]]; newSeg _ GGSegment.MakeConic[p0, p1, p2, 0.7]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; random: Random.RandomStream _ Random.Create[10000,0]; NewV: PROC RETURNS[REAL] = {RETURN[Random.NextInt[random]/10000.0]}; GetPt: PROC[p0, dir: Point, maxL: REAL] RETURNS [pt: Point] = { scale1: REAL _ NewV[]*maxL; angle: REAL _ 180*NewV[]-90; --range -90..90 pt _ GGVector.Add[GGVector.Scale[GGVector.VectorPlusAngle[dir,angle], scale1], p0]; }; GetPtSequence: PROC[p0,p1: Point, n: NAT] RETURNS [CubicSplines.KnotSequence] ={ points: CubicSplines.KnotSequence _ NEW[CubicSplines.KnotSequenceRec[n+2]]; dir: Point _ GGVector.Sub[p1,p0]; inc: REAL _ GGVector.Distance[p0,p1]/(n-2); maxL: REAL _ inc; points[0] _ p0; FOR i: NAT IN [1..points.length-1) DO points[i] _ GetPt[p0, dir, maxL]; maxL _ maxL+inc; ENDLOOP; points[points.length-1] _ p1; RETURN[points]; }; AddSegment: PROC[traj: Traj, newSeg: Segment, next: GGObjects.SegAndIndex] = { traj.segments _ Rosary.Cat[ Rosary.Substr[traj.segments, 0, next.index], Rosary.FromItem[newSeg], Rosary.Substr[traj.segments, next.index+1, GGObjects.HiSegment[traj]-next.index] ]; }; SetBezier: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; p0, p1, p2, p3: Point; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO length: REAL _ GGVector.Distance[next.seg.lo, next.seg.hi]; dir: Point _ GGVector.Sub[p3,p0]; p0 _ next.seg.lo; p1 _ GetPt[p0, dir,length*0.7]; p2 _ GetPt[p0, dir,length]; p3 _ next.seg.hi; newSeg _ GGSegment.MakeBezier[p0, p1, p2, p3]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SetSpline: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO length: REAL _ GGVector.Distance[next.seg.lo, next.seg.hi]; type: CubicSplines.SplineType _ naturalAL; nKnots: INT _ Real.RoundLI[10*NewV[]]; cps: CubicSplines.KnotSequence _ GetPtSequence[next.seg.lo, next.seg.hi, nKnots]; newSeg _ GGSegment.MakeCubicSpline[cps, type]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; Close: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { traj: Traj; firstPoint, lastPoint: Point; seg: Segment; [traj,----,----,----,----] _ GGCaret.GetChair[gargoyleData.caret]; IF traj = NIL THEN { GGError.Append["There is no caret trajectory to close.", oneLiner]; GGError.Blink[]; RETURN; }; IF traj.role = fence OR traj.role = hole THEN { GGError.Append["That trajectory is already closed.", oneLiner]; GGError.Blink[]; RETURN; }; GGError.Append["The caret trajectory will be closed.", oneLiner]; firstPoint _ GGObjects.FetchJointPos[traj, 0]; lastPoint _ GGObjects.LastJointPos[traj]; seg _ GGSegment.MakeLine[lastPoint, firstPoint]; GGObjects.CloseWithSegment[traj, seg, lo]; GGObjects.SetFillColor[GGObjects.OutlineOfTraj[traj], Imager.MakeGray[0.5]]; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; ShowPoints: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO seq.traj.visibleJoints _ TRUE; ENDLOOP; }; HidePoints: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO seq.traj.visibleJoints _ FALSE; ENDLOOP; }; Refresh: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; DisableRefresh: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { gargoyleData.refresh.suppressRefresh _ TRUE; }; EnableRefresh: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { gargoyleData.refresh.suppressRefresh _ FALSE; }; TestGravity: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { xRandomStream, yRandomStream: Random.RandomStream; testPoint: Point; x, y: INT; totalCount: NAT _ 0; s: IO.STREAM; resultPoint: Point; feature: REF ANY; countRope: Rope.ROPE; environ: GGGravity.ObjectBag; xRandomStream _ Random.Create[gargoyleData.actionArea.cw]; yRandomStream _ Random.Create[gargoyleData.actionArea.ch]; environ _ GGGravity.CreateObjectBag[]; GGAlign.AddItemsForAction[gargoyleData, environ, $SelectPoint]; IF environ = NIL THEN { GGError.Append["Add some trajectories to test gravity.", oneLiner]; GGError.Blink[]; RETURN; }; gargoyleData.hitTest.environ _ environ; GGWindow.Painter[$PaintAlign, gargoyleData]; gargoyleData.hitTest.hitCount _ 0; UNTIL totalCount > 1000 DO IF gargoyleData.aborted THEN { gargoyleData.aborted _ FALSE; EXIT; }; x _ Random.NextInt[xRandomStream]; y _ Random.NextInt[yRandomStream]; testPoint _ [x, y]; testPoint _ GGWindow.ScreenToWorld[testPoint, gargoyleData.camera]; gargoyleData.refresh.spotPoint _ testPoint; [resultPoint, feature] _ GGGravity.Map[testPoint, gargoyleData.hitTest.tolerance, environ, gargoyleData]; IF feature # NIL THEN { gargoyleData.refresh.hitPoint _ resultPoint; GGWindow.Painter[$PaintHitLine, gargoyleData]; gargoyleData.hitTest.hitCount _ gargoyleData.hitTest.hitCount + 1; } ELSE { GGWindow.Painter[$PaintSpot, gargoyleData]; }; totalCount _ totalCount + 1; ENDLOOP; s _ IO.ROS[]; s.PutF["Tested %g total points. %g were hits", [integer[totalCount]], [integer[gargoyleData.hitTest.hitCount]]]; countRope _ IO.RopeFromROS[s]; GGError.Append[countRope, oneLiner]; }; DrawTouchPoints: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$PaintTouchPoints, gargoyleData]; }; DescribeTouchPoints: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGTouch.DescribeAllTouchPoints[gargoyleData]; }; DrawBoundBoxes: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$PaintBoundBoxes, gargoyleData]; }; DrawSelectionBox: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$PaintSelectionBox, gargoyleData]; }; Typescript: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { newViewer: Viewer; inHandle, outHandle: IO.STREAM; [inHandle, outHandle, newViewer] _ MakeNewViewerAndHandle[]; GGError.SetErrorStream[outHandle]; gargoyleData.debug.typescript _ newViewer; }; MakeNewViewerAndHandle: PRIVATE PROC [] RETURNS [in, out: IO.STREAM, newViewer: Viewer] = { newViewer _ ViewerOps.CreateViewer[ flavor: $TypeScript, info: [ name: "Gargoyle Script", menu: NIL, data: NIL, iconic: TRUE, column: right, scrollable: TRUE, icon: unInit ], paint: FALSE]; ViewerOps.SetOpenHeight[newViewer, 120]; ViewerOps.OpenIcon[icon: newViewer, closeOthers: FALSE, bottom: TRUE, paint: TRUE]; [in, out] _ ViewerIO.CreateViewerStreams["gargoyle script", newViewer, NIL, TRUE]; }; SlackLog: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGDrawProcess.OutputLog[]; }; DescribeCaretObject: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { chair: Traj; description, msgRope: Rope.ROPE; isJoint: BOOL; jointNum: NAT; seg: Segment; [chair, isJoint, ----, jointNum, seg] _ GGCaret.GetChair[gargoyleData.caret]; IF isJoint THEN { description _ GGDescribe.DescribeJoint[chair, jointNum]; } ELSE { segNum: INT; segNum _ GGObjects.IndexOfSegment[seg, chair]; IF segNum = -1 THEN description _ Rope.Concat["Nonexistent segment of ", GGDescribe.DescribeTraj[chair]] ELSE description _ GGDescribe.DescribeSegment[chair, segNum]; }; msgRope _ IO.PutFR["Caret is on %g.", [rope[description]]]; GGError.Append[msgRope, oneLiner]; }; END. ΨGGEventImplA.mesa Last edited by Bier on October 1, 1985 8:58:32 pm PDT Contents: Once an event reaches the front of the slack-process queue, it is dispatched to one of the procedures in this module. Stone, August 9, 1985 2:38:57 pm PDT File Operations TIMING VARIABLES The Painting Call START TIMING Master Menu Line Hierarchy Menu Curve Menu Choose a random p1: Choose a random p near the line p0, p2: Choose a random p1 and p2: Choose a random number of knots and positions: Edit Curve Menu View Menu Debug Menu Within the bounds of the viewer, randomly choose mouse positions. See if that mouse position is in range of any object. If so, draw a dot at that point. Repeat until 100 points have been drawn. Κ)˜Ihead1™J™5™€Icode™$—J™šΟk ˜ JšœΉ˜ΉJ˜—šœœ˜Jšœσ˜ϊJšœ ˜—Jš˜J˜Jšœ œ˜%Jšœœ ˜5Jšœœ!˜3Jšœœ˜!Jšœœ˜3Jšœ œ˜%Jšœœ˜!Jšœœ'˜?Jšœ œ˜%Jšœ œ˜'Jšœœ˜Jšœœ˜1Jšœ œ˜+Jšœœ!˜7Jšœœ"˜9Jšœœ˜#J˜$J˜J™J™J™JšΟnœœœ œœœœ#˜MJšžœœœ œœœœ#˜MJšžœœœ œœœœ#˜KJšžœœœ œœœœ#˜MJšžœœœ œœœœ#˜MšΠbn œœœ œœœœ!˜PIprocšœ˜Mšœœ˜"Mšœ œ˜M˜%Jšœ™Jšœœ˜Jšœœ˜Jšœ œ˜Jšœœ˜M™šžœœ˜/M˜"Mšœ2˜2M˜M˜—Mšœ,˜,Jšœœœ˜'JšΟbœ)˜-Jšœ œ˜šœ œœ˜)šœœ œœ˜*Jšœ œ˜Jšœ˜ J˜—Jšœ˜—Jšœœ œœ˜Jšœ*˜*Jšœ œB˜NJšœ˜Jšœ ™ Jš ˜Jšœ6˜6Jšœ˜Jš ˜Jšœ1˜1Jšœ œ3˜?Jšœ˜M˜J˜J˜—J™J™J˜J™J˜šžœœœ œœœœ!˜LM˜Mšœ˜Mšœ<˜<š œ œœDœ œ˜lMšœ6˜6Mšœ4˜4Mšœ3˜3Mšœ6˜6Mšœœ˜Mšœœ˜,šœ˜Mšœ5˜5Mšœ.˜.M˜—šœ˜Mšœ2˜2šœ#œ˜+Mšœ˜Mšœœ˜ MšœœΟc)˜8šœ ˜ Mšœ\˜\Mšœ˜M˜—Mšœœ˜Mšœ˜—šœ˜šœ œ‘#˜5Mšœ;˜;Mšœ4˜4M˜—šœ‘Ά˜½š œœœœ4œ˜sM˜OM˜M˜—šœ˜Mšœ3˜3Mšœ+˜+šœœ˜#MšœF˜FMšœJ˜JMšœT˜TM˜—šœ˜MšœO˜OMšœO˜OMšœT˜TM˜—M˜—M˜—M˜—M˜—Mšœœ˜—Mšœ˜Jšœ2˜2J˜J˜—š ž œ œ œœœœ!˜OMšœ+˜+Mšœ)˜)Jšœ2˜2M˜J˜—Jšœœœœ˜(J™J™ J˜š ž œ œ œœœœ!˜QJ˜J˜J˜ J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜šœtœ œ˜ŽJšœžœ˜6J˜—Jšœ˜—Jšœ˜Jšœ2˜2Jšœ˜—šžœœœ œœœœ!˜LJ˜J˜J˜ J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜Jšœtœ œ˜Ž™J˜J˜Jšœ>˜>Jšœžœ ˜'J˜—Jšœ˜—Jšœ˜Jšœ2˜2J˜—š žœ œ œœœœ!˜NJ˜J˜J˜ J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜šœtœ œ˜ŽJ˜J˜Jšœ>˜>Jšœž œ˜.J˜—Jšœ˜—Jšœ˜Jšœ2˜2Jšœ˜—J˜5Jš žœœœœœ"˜Dšžœœœœ˜?J™'Jšœœ ˜Jšœœ‘˜,J˜SJ˜—šž œœœœ˜PJšœ$œ$˜KJšœ!˜!Jšœœ"˜+Jšœœ˜J˜šœœœ˜%Jšœ!˜!J˜Jšœ˜—Jšœ˜Jšœ ˜J˜J˜—šž œœ>˜NJšœ΅˜΅J˜J˜—š Ÿ œ œ œœœœ!˜OJ˜J˜J˜ J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜Jšœtœ œ˜Ž™Jšœœ/˜;Jšœ!˜!J˜Jšœ˜Jšœ˜J˜Jšœž œ˜.J˜—Jšœ˜—Jšœ˜Jšœ2˜2J˜—š ž œ œ œœœœ!˜OJ˜J˜J˜ J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜Jšœtœ œ˜Ž™.Jšœœ/˜;J˜*Jšœœ˜&JšœQ˜QJšœžœ ˜.J˜—Jšœ˜—Jšœ˜Jšœ2˜2Jšœ˜—J™J™J˜šžœœœ œœœœ!˜KMšœ ˜ Mšœ˜M˜ Mš œ‘œ‘œ‘œ‘œ)˜Bšœœœ˜MšœC˜CMšœ˜Mšœ˜M˜—šœœœ˜/Mšœ?˜?Mšœ˜Mšœ˜M˜—MšœA˜AMšœ.˜.Mšœ)˜)Mšœ0˜0Mšœ*˜*MšœL˜LJšœ2˜2M˜M˜—šž œœœ œœœœ!˜PMšœM˜MšœPœœ˜eM˜—Mšœ˜M˜M˜—šž œœœ œœœœ!˜PMšœM˜MšœPœœ˜eM˜—Mšœ˜M˜J˜—J™J™ J™šžœœœ œœœœ!˜MJšœ2˜2J˜—J˜š žœ œ œœœœ!˜TJšœ,˜,J˜J˜—š ž œ œ œœœœ!˜SJšœ-˜-J˜J˜—J™ J˜šž œœœ œœœœ!˜QM™ΔMšœ2˜2Mšœ˜Mšœœ˜ Mšœ œ˜Mšœœœ˜ Jšœ˜Jšœ œœ˜Mšœœ˜Mšœ˜Mšœ:˜:Mšœ:˜:Mšœ&˜&Mšœ?˜?šœ œœ˜MšœC˜CM˜Mšœ˜M˜—Mšœ'˜'Mšœ,˜,Mšœ"˜"šœ˜šœœ˜Mšœœ˜Mšœ˜M˜—Mšœ"˜"Mšœ"˜"M˜MšœC˜CMšœ+˜+Mšœi˜išœ œœ˜Mšœ,˜,Mšœ.˜.MšœB˜BM˜—šœ˜Mšœ+˜+M˜—M˜—Mšœ˜Mšœœœ˜ Mšœq˜qMšœ œ˜Mšœ$˜$M˜M˜—šžœœœ œœœœ!˜UJšœ2˜2J˜—šžœœœ œœœœ!˜YJšœ-˜-J˜—šžœœœ œœœœ!˜TJšœ1˜1J˜—šžœœœ œœœœ!˜VJšœ3˜3J˜—šž œœœ œœœœ!˜PJšœ˜Jšœœœ˜Jšœ<˜