DIRECTORY Event USING [GetOctava, GetScoreIndex, Octava], MusicDefs USING [CacheRec, EventPTR, EventRec, NotePTR, ScorePTR, ScoreRec, SetDirty, SheetPTR, StavesPTR, StylePTR, StyleRec, SyncPTR, Time], Note USING [Delta, Free, InVoice], Piece USING [], Score USING [GetKey, ShowPitch], Sheet USING [FindLine, Height, NearestTime, New, NextLine]; PieceImplA: CEDAR PROGRAM IMPORTS Event, MusicDefs, Note, Score, Sheet EXPORTS Piece = BEGIN OPEN MusicDefs; dataStructureInFlux: PUBLIC BOOLEAN _ FALSE; AddEvent: PUBLIC PROC[score: ScorePTR, event: EventPTR] = { IF event = NIL THEN RETURN; dataStructureInFlux _ TRUE; FOR i: NAT DECREASING IN[0..score.length) DO IF score.event[i] = event THEN ERROR; IF score.event[i].time < event.time THEN { score.event[i+1] _ event; event _ NIL; EXIT }; IF score.event[i].time = event.time AND ~LessThan[event, score.event[i]] THEN {score.event[i+1] _ event; event _ NIL; EXIT}; score.event[i+1] _ score.event[i]; ENDLOOP; IF event#NIL THEN score.event[0] _ event; score.length _ score.length + 1; dataStructureInFlux _ FALSE; }; LessThan: PROC[a, b: EventPTR] RETURNS[BOOLEAN] = { IsStyle: PROC[e: EventPTR] RETURNS[BOOL] ~ { WITH e SELECT FROM e: StavesPTR => RETURN[e.staves=style]; ENDCASE => RETURN[FALSE]; }; SELECT TRUE FROM a.type = staves AND IsStyle[a] => RETURN[TRUE]; b.type = staves AND IsStyle[b] => RETURN[FALSE]; a.type = keySignature => RETURN[TRUE]; b.type = keySignature => RETURN[FALSE]; a.type = measure => RETURN[TRUE]; b.type = measure => RETURN[FALSE]; a.type = metronome => RETURN[TRUE]; b.type = metronome => RETURN[FALSE]; a.type = timeSignature => RETURN[TRUE]; b.type = timeSignature => RETURN[FALSE]; a.type = staves => RETURN[TRUE]; b.type = staves => RETURN[FALSE]; ENDCASE => RETURN[TRUE]; }; RemoveEvent: PUBLIC PROC[score: ScorePTR, event: EventPTR, free: BOOLEAN _ FALSE] = { length: CARDINAL _ 0; octava: EventPTR _ NIL; IF Event.Octava[event] AND free THEN octava _ Event.GetOctava[score, NARROW[event]]; FOR i: CARDINAL IN [0..score.length) DO IF score.event[i] = event THEN LOOP; IF i # length THEN score.event[length] _ score.event[i]; length _ length+1; ENDLOOP; WITH event SELECT FROM sync: SyncPTR => FOR i: NAT IN[0..sync.length) DO sync.note[i].sync _ NIL ENDLOOP; ENDCASE; score.length _ length; score.event[score.length] _ NIL; IF free AND octava # NIL THEN { SetDirty[score, octava.time, octava.time]; RemoveEvent[score, octava, FALSE]; }; }; nullScore: ScorePTR _ NEW[ScoreRec[0]]; New: PUBLIC PROC[length: CARDINAL, auxiliary: BOOL] RETURNS[score: ScorePTR] = { score _ NEW[ScoreRec[length] _ [event: ]]; IF auxiliary THEN { IF score.cache = NIL THEN score.cache _ NEW[CacheRec]; IF score.sheet = NIL THEN score.sheet _ Sheet.New[100]; IF score.style = NIL THEN score.style _ NewStyle[20]; }; }; NewStyle: PROC[length: NAT] RETURNS[StylePTR] = { style: StylePTR ~ NEW[StyleRec[length]]; style[0] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 60, length: 4, staff: [[72,-32],[48,-88],[27,-136],[3,-196]] ]]]; style[1] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 80, length: 4, staff: [[48,-32],[48,-32],[48,-32],[48,-32]] ]]]; style[2] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 85, length: 4, staff: [[48,-32],[48,-32],[27,-125],[27,-125]] ]]]; style[12] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 85, length: 4, staff: [[48,-32],[48,-32],[27,-150],[27,-150]] ]]]; style[3] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 75, length: 4, staff: [[48,-32],[48,-32],[27,-110],[27,-185]] ]]]; style[13] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 75, length: 4, staff: [[48,-32],[48,-32],[27,-130],[27,-220]] ]]]; style[4] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 75, length: 4, staff: [[48,-32],[48,-110],[27,-185],[27,-260]] ]]]; FOR i: NAT IN[0..length) DO IF style[i]=NIL THEN style[i] _ NEW[EventRec[staves] _ [variant: staves[ height: 0, offset: 0, length: 0, staff: [[0, 0],[0, 0],[0, 0],[0, 0]]]]]; ENDLOOP; style.length _ length; RETURN[style]; }; Free: PUBLIC PROC[score: ScorePTR] = { }; Sort: PUBLIC PROC[score: ScorePTR] = { FOR i: CARDINAL IN [0..score.length) DO FOR j: CARDINAL IN (i..score.length) DO a: EventPTR ~ score.event[i]; b: EventPTR ~ score.event[j]; IF a.time > b.time THEN { score.event[i] _ b; score.event[j] _ a } ELSE IF a.time = b.time THEN WITH a SELECT FROM a: SyncPTR => WITH b SELECT FROM b: SyncPTR => { IF a.note[0]=NIL OR b.note[0]=NIL OR a.note[0].toc < b.note[0].toc THEN NULL ELSE { score.event[i] _ b; score.event[j] _ a }; }; ENDCASE; ENDCASE; ENDLOOP; ENDLOOP; }; CleanUpEvents: PUBLIC PROC[score: ScorePTR] = { length: CARDINAL _ 0; FOR i: CARDINAL DECREASING IN [0..score.length) DO WITH score.event[i] SELECT FROM sync: SyncPTR => { IF sync.length=0 THEN score.event[i] _ NIL ELSE { score.event[length] _ score.event[i]; length _ length+1 }; }; ENDCASE; ENDLOOP; FOR i: CARDINAL IN [length..score.length) DO score.event[i] _ NIL; ENDLOOP; score.length _ length; score[score.length] _ NIL; }; CleanUpNotes: PUBLIC PROC[score: ScorePTR] = { FOR i: CARDINAL DECREASING IN [0..score.length) DO WITH score.event[i] SELECT FROM sync: SyncPTR => { FOR j: CARDINAL DECREASING IN [0..sync.length) DO IF sync.note[j].value # unknown THEN LOOP; IF sync.note[j].duration # 0 THEN LOOP; Note.Free[score, sync.note[j]]; -- may remove the sync from the score ENDLOOP; }; ENDCASE; ENDLOOP; CleanUpEvents[score]; }; NearestEvent: PUBLIC PROC[score: ScorePTR, t: Time, syncsOnly: BOOLEAN _ FALSE] RETURNS[index: CARDINAL] = { delta: Time _ 10000; index _ 0; FOR binary: CARDINAL _ 8192, binary/2 UNTIL binary = 0 DO IF index+binary >= score.length THEN LOOP; IF score.event[index+binary].time <= t THEN index _ index+binary; IF score.event[index].time = t THEN EXIT; ENDLOOP; FOR i: CARDINAL IN [(IF index < 5 THEN 0 ELSE index-5)..MIN[index+5, score.length]) DO IF syncsOnly AND score.event[i].type # sync THEN LOOP; IF ABS[score.event[i].time-t] > delta THEN LOOP; index _ i; delta _ ABS[score.event[i].time-t]; ENDLOOP; IF syncsOnly AND index # score.length AND score.event[index].type # sync THEN index _ score.length; }; NearestNote: PUBLIC PROC[score: ScorePTR, x, y: INTEGER] RETURNS[note: NotePTR] = { n: NotePTR; key: INTEGER; sync: SyncPTR; l, next: CARDINAL; time, dt, t: Time _ 11; sheet: SheetPTR _ score.sheet; height, dy, show: INTEGER _ 8; [time, height] _ Sheet.NearestTime[sheet, x, y]; next _ Sheet.FindLine[sheet, time]; time _ time - (sheet.width - sheet.section[next].x); l _ Sheet.FindLine[sheet, time]; height _ height + (sheet.section[next].y - sheet.section[l].y); FOR k: CARDINAL IN [0..2] DO FOR i: CARDINAL IN [0..score.length) DO IF score.event[i].type # sync THEN LOOP; IF score.event[i].time < time - 40 THEN LOOP; IF score.event[i].time > time + 40 THEN EXIT; IF score.event[i].time < sheet.section[l].time THEN LOOP; IF score.event[i].time >= sheet.section[next].time THEN EXIT; sync _ NARROW[score.event[i]]; FOR j: CARDINAL IN [0..sync.length) DO n _ sync.note[j]; IF ~Note.InVoice[n, score.sheet.voice] THEN LOOP; t _ ABS[score[i].time+5+Note.Delta[score.sheet, n]-time]; key _ Score.GetKey[score, n.sync.time]; show _ Score.ShowPitch[score.sheet, n.pitch, n.spelled, key]; y _ ABS[height-Sheet.Height[sheet, n.sync.time, show, n.staff]]; IF y+t > dy+dt THEN LOOP; IF y+t = dy+dt AND t > dt THEN LOOP; dt _ t; dy _ y; note _ n; ENDLOOP; ENDLOOP; time _ time+ (sheet.width - sheet.section[next].x); height _ height- (sheet.section[next].y - sheet.section[l].y); l _ next; next _ Sheet.NextLine[sheet, l]; ENDLOOP; IF dt > 10 OR dy > 7 THEN note _ NIL; }; DeleteEvent: PUBLIC PROC[score: ScorePTR, event: EventPTR] = { octava: StavesPTR _ NIL; index: CARDINAL _ Event.GetScoreIndex[score, event]; IF Event.Octava[event] THEN octava _ Event.GetOctava[score, NARROW[event]]; RemoveEvent[score, event]; IF octava # NIL THEN { SetDirty[score, octava.time, octava.time]; RemoveEvent[score, octava]; }; }; END. NearestObject: PUBLIC PROC[score: ScorePTR, x, y: INTEGER] RETURNS[obj: ObjectType, p: LONG POINTER _ NIL] = { n: NotePTR; l: CARDINAL; key: INTEGER; staves: StavesPTR; time, dt, t: Time _ 11; s, next: CARDINAL _ 0; sheet: SheetPTR _ score.sheet; height, dy, show: INTEGER _ 8; [time, height] _ Sheet.NearestTime[sheet, x, y]; next _ Sheet.FindLine[sheet, time]; time _ time - (sheet.width - sheet.section[next].x); l _ Sheet.FindLine[sheet, time]; height _ height + (sheet.section[next].y - sheet.section[l].y); FOR k: CARDINAL IN [0..2] DO FOR i: CARDINAL IN [0..score.beamHeap.length) DO IF score.beamHeap.beam[i].beam # NIL AND score.beamHeap.beam[i].beam.beamed THEN LOOP; IF score.beamHeap.beam[i].sync1.time-5 > time THEN LOOP; IF score.beamHeap.beam[i].sync2.time+5 < time THEN LOOP; IF ~Beam.InVoice[score.beamHeap.beam[i], score.sheet.voice] THEN LOOP; y _ Beam.Height[sheet, score.beamHeap.beam[i], time]; IF ABS[y-height]+4 > dt+dy THEN LOOP; IF ABS[y-height]+4 = dt+dy THEN IF y > height THEN LOOP; dt _ 4; dy _ ABS[y-height]; IF time < (score.beamHeap.beam[i].sync1.time+score.beamHeap.beam[i].sync2.time+4)/2 THEN obj _ leftBeam ELSE obj _ rightBeam; p _ score.beamHeap.beam[i]; ENDLOOP; FOR i: CARDINAL IN [s..score.length) DO IF score.event[i].time < time - 300 THEN LOOP; IF score.event[i].time > time + 300 THEN {s _ i; EXIT}; IF score.event[i].time < sheet.section[l].time THEN LOOP; IF score.event[i].type = sync THEN { -- ties sync: SyncPTR _ Event.Sync[score.event[i]]; FOR j: CARDINAL IN [0..sync.length) DO n _ sync.note[j]; IF ~Note.InVoice[n, score.sheet.voice] THEN LOOP; IF n.tie = NIL THEN LOOP; IF n.sync.time < time OR n.tie.sync.time > time THEN LOOP; t _ ABS[(n.sync.time+n.tie.sync.time)/2-time]; key _ Score.GetKey[score, n.sync.time]; show _ Score.ShowPitch[score.sheet, n.pitch, n.spelled, key]; y _ ABS[height-(Sheet.Height[sheet, n.sync.time, show, n.staff]+n.tieHeight/2)]; IF y+t > dy+dt THEN LOOP; IF y+t = dy+dt THEN IF t > dt THEN LOOP; dt _ t; dy _ y; obj _ tie; p _ n; ENDLOOP}; IF score.event[i].time >= sheet[next].time THEN LOOP; IF ABS[score.event[i].time-time] > 40 THEN LOOP; IF score.event[i].type = staves THEN { octava: StavesPTR _ NIL; staves: StavesPTR _ Event.Staves[score.event[i]]; staff, top, bottom: INTEGER _ staves.value; t _ staves.time; IF staves.staves = clef THEN t _ t+6; IF ABS[t-time]+6 > dt + dy THEN LOOP; IF ABS[t-time]+6 = dt+dy AND t < time THEN LOOP; IF staves.staves = octava2 THEN staves _ Event.GetOctava[score, staves]; SELECT staves.staff[staff].pitch FROM 60, 15 => {top _ staves.height+5; bottom _ staves.height-5}; ENDCASE => {top _ 32; bottom _ 0}; IF height > Sheet.Height[sheet, score.event[i].time, , staff]+top THEN LOOP; IF height < Sheet.Height[sheet, score.event[i].time, , staff]+bottom THEN LOOP; dt _ ABS[t-time]; dy _ 6; p _ score.event[i]; obj _ measure; LOOP}; IF score.event[i].type # sync THEN { IF ABS[score.event[i].time-time]+6 > dt + dy THEN LOOP; IF ABS[score.event[i].time-time]+6 = dt+dy AND score.event[i].time < time THEN LOOP; IF score.event[i].type = staves AND score.event[i].time < 1 THEN LOOP; -- don't touch the first one staves _ sheet.section[Sheet.FindSection[sheet, score[i].time]].staves; IF height > Sheet.Height[sheet, score.event[i].time, , 0]+32 THEN LOOP; IF height < Sheet.Height[sheet, score.event[i].time, , staves.length-1] THEN LOOP; dt _ ABS[score.event[i].time-time]; dy _ 6; p _ score.event[i]; obj _ measure; LOOP}; IF score.event[i].type = sync THEN { -- notes sync: SyncPTR _ Event.Sync[score.event[i]]; FOR j: CARDINAL IN [0..sync.length) DO IF (n _ sync.note[j]) = NIL THEN EXIT; IF ~Note.InVoice[n, score.sheet.voice] THEN LOOP; t _ ABS[score.event[i].time+5+Note.Delta[score.sheet, n]-time]; y _ ABS[height-Sheet.Height[sheet, n.sync.time, n.pitch, n.staff]]; IF y+t > dy+dt THEN LOOP; IF y+t = dy+dt AND t > dt THEN LOOP; dt _ t; dy _ y; p _ n; obj _ note; ENDLOOP}; ENDLOOP; -- end of this line, go to next time _ time+ (sheet.width - sheet.section[next].x); height _ height- (sheet.section[next].y - sheet.section[l].y); l _ next; next _ Sheet.NextLine[sheet, l]; ENDLOOP; IF dt > 10 OR dy > 7 THEN p _ NIL; }; ¨PieceImplA.mesa Copyright (C) 1983, 1984 Xerox Corporation. All rights reserved. Author: John Maxwell Last Edited by: Maxwell, November 22, 1983 1:00 pm Last Edited by: Doug Wyatt, June 14, 1984 9:56:13 pm PDT **************************************************************************** data abstractions for a piece CONSTRAINT: score.event[i-1].time <= score.event[i].time <= score.event[i+1].time CONSTRAINT: score.event[i] # NIL for all i such that 0 <= i < score.length CONSTRAINT: score.event[score.length] = NIL CONSTRAINT: score.event[i] # score.event[j] for all i # j < score.length **************************************************************************** any procedure that inserts syncs should process syncs in decreasing order IF score.length+1 = score.max THEN score _ New[score.max+100, TRUE, score]; insert sync IF free THEN zone.FREE[@event]; zone.FREE[@octava] oldSize: CARDINAL; nullSize: CARDINAL _ SIZE[ScoreRec[0]]; score _ Utility.NewSegment[SIZE[ScoreRec[length]], length, nullSize-1]; IF old = NIL THEN old _ nullScore; -- gets the default values for us oldSize _ SIZE[ScoreRec[old.length]]; Inline.LongCOPY[from: old, nwords: nullSize-1, to: score]; -- skip 'max' Inline.LongCOPY[from: old+nullSize, nwords: oldSize-nullSize, to: score+nullSize]; IF score.max # length THEN ERROR; -- check that it worked. IF old # nullScore THEN { SetBackPointers[old, score]; Utility.FreeSegment[old]}; pianoroll one staff two staffs three staffs four staffs IF score.beamHeap # NIL THEN { -- free all of the beams FOR i: CARDINAL IN [0..score.beamHeap.length) DO zone.FREE[@score.beamHeap[i]]; -- no need to carefully dismantle ENDLOOP; Utility.FreeSegment[score.beamHeap]}; IF score.chordHeap # NIL THEN { -- free all of the chords FOR i: CARDINAL IN [0..score.chordHeap.length) DO zone.FREE[@score.chordHeap[i]]; -- no need to carefully dismantle ENDLOOP; Utility.FreeSegment[score.chordHeap]}; FOR i: CARDINAL IN [0..score.length) DO IF score.event[i] = NIL THEN LOOP; IF score.event[i].type = sync THEN { sync: SyncPTR = Event.Sync[score.event[i]]; FOR j: CARDINAL IN [0..sync.length) DO zone.FREE[@sync.note[j]]; ENDLOOP}; zone.FREE[@score.event[i]]; ENDLOOP; SetBackPointers[score, NIL]; Utility.FreeSegment[score]; SetBackPointers: PROC[old, new: ScorePTR] = { IF Selection.selection.score = old THEN Selection.selection.score _ new; IF Selection.selection.score2 = old THEN Selection.selection.score2 _ new; SIGNAL Overflow[old, new]; }; useful when going from physical to logical files **************************************************************************** what is being pointed at? **************************************************************************** the above will fail when the p isn't strictly ordered zone.FREE[@octava] Utility.FreeEvent[@event]; left and right corners of a beam measure sections, signatures and other events IF octava # NIL THEN staves _ LOOPHOLE[@octava.event] ELSE staves _ LOOPHOLE[@score[i].event]; Êd˜šœ™Jšœ@™@Jšœ™Jšœ2™2Jšœ8™8—J˜šÏk ˜ Jšœœ$˜/Jšœ œ˜ŽJšœœ˜"Jšœœ˜Jšœœ˜ Jšœœ0˜;J˜—Jšœ œ˜Jšœ%˜,Jšœ˜ Jšœœœ ˜J˜Jšœœœœ˜,J˜JšœL™LJšœ™JšœQ™QJšœJ™JJšœ+™+JšœH™HJšœL™LJ˜šÏnœœœ&˜;JšœI™IJšœ œœœ˜Jšœœœ ™KJšœ ™ Jšœœ˜š œœ œœ˜,Jšœœœ˜%Jšœ"œ%œœ˜Yšœ"œ"˜IJšœ$œœ˜3—J˜"Jšœ˜—Jšœœœ˜)J˜ Jšœœ˜Jšœ˜—J˜šžœœœœ˜3šžœœœœ˜,šœœ˜Jšœœ˜'Jšœœœ˜—J˜—šœœ˜Jšœœœœ˜/Jšœœœœ˜0Jšœœœ˜&Jšœœœ˜'Jšœœœ˜!Jšœœœ˜"Jšœœœ˜#Jšœœœ˜$Jšœœœ˜'Jšœœœ˜(Jšœœœ˜ Jšœœœ˜!Jšœœœ˜—Jšœ˜J˜—š ž œœœ)œœ˜UJšœœ˜Jšœœ˜Jšœœœ!œ ˜Tšœœœ˜'Jšœœœ˜$Jšœ œ&˜8Jšœœ˜—šœœ˜Jš œœœœœ œ˜RJšœ˜—J˜Jšœœ˜ Jšœœœ ™šœœ œœ˜ J˜*Jšœœ˜#Jšœœ ™Jšœ˜—Jšœ˜J˜—Jšœœ˜'J˜š žœœœ œ œœ˜PJšœœ˜*Jšœ œ™Jšœ œœ™'Jšœœ(™GJšœœœÏc!™EJšœ œ™%Jšœ;Ÿ ™HJ™RJšœœœŸ™:šœœ™J™J™—šœ œ˜Jšœœœœ ˜6Jšœœœ˜7Jšœœœ˜5Jšœ˜—Jšœ˜J˜—šžœœ œœ˜1Jšœœ˜(Jšœ ™ šœ œ%˜3Jšœ!˜!Jšœ-˜-Jšœ˜—Jšœ ™ šœ œ%˜3Jšœ!˜!Jšœ,˜,Jšœ˜—Jšœ ™ šœ œ%˜3Jšœ!˜!Jšœ.˜.Jšœ˜—šœ œ%˜4Jšœ!˜!Jšœ.˜.Jšœ˜—Jšœ™šœ œ%˜3Jšœ!˜!Jšœ.˜.Jšœ˜—šœ œ%˜4Jšœ!˜!Jšœ.˜.Jšœ˜—Jšœ ™ šœ œ%˜3Jšœ!˜!Jšœ/˜/Jšœ˜—šœœœ ˜šœ œœ œ%˜HJšœI˜I—Jšœ˜—J˜Jšœ˜Jšœ˜J˜—šžœœœ˜%Jšœ˜šœœœŸ™7šœœœ™0JšœœŸ!™@Jšœ™—J™%—šœœœŸ™9šœœœ™1JšœœŸ!™AJšœ™—J™&—šœœœ™'Jšœœœœ™"šœœ™$J™+šœœœ™&Jšœœ™Jšœ™ ——Jšœœ™Jšœ™—Jšœœ™J™Jšœ˜J˜—šžœœ™,Jšœ™Jšœ!œ!™HJšœ"œ"™JJšœ™Jšœ™J™—J˜šžœœœ˜&Jšœ1™1šœœœ˜'šœœœ˜'Jšœ˜Jšœ˜Jšœœ+˜Bš œœœœœ˜/šœœœ˜ ˜Jš œ œœ œœœ˜LJšœ,˜0J˜—Jšœ˜—Jšœ˜—Jšœ˜—Jšœ˜—Jšœ˜J˜—šž œœœ˜/Jšœœ˜š œœ œœ˜2šœœ˜˜Jšœœ˜*Jšœ=˜AJ˜—Jšœ˜—Jšœ˜—Jš œœœœœœ˜KJ˜Jšœœ˜Jšœ˜J˜—šž œœœ˜.š œœ œœ˜2šœœ˜˜š œœ œœ˜1Jšœœœ˜*Jšœœœ˜'Jšœ Ÿ%˜EJšœ˜—J˜—Jšœ˜—Jšœ˜—J˜Jšœ˜J˜—J™JšœL™LJšœ™JšœL™LJ˜šž œœœ&œœœœ˜lJ˜J˜ šœ œœ ˜9Jšœœœ˜*Jšœ%œ˜AJšœœœ˜)Jšœ˜—Jšœ5™5šœœœœ œœ œ˜VJšœ œœœ˜6Jšœœ œœ˜0Jšœœ˜.Jšœ˜—šœ œœ ˜IJšœ˜—Jšœ˜J˜—š ž œœœœœ˜SJ˜ Jšœœ˜ J˜Jšœ œ˜J˜J˜Jšœœ˜J˜0J˜#J˜4J˜!J˜?šœœœ˜šœœœ˜'Jšœœœ˜(Jšœ!œœ˜-Jšœ!œœ˜-Jšœ-œœ˜9Jšœ1œœ˜=Jšœœ˜šœœœ˜&J˜Jšœ%œœ˜1Jšœœ2˜9J˜'J˜=Jšœœ9˜@Jšœ œœ˜Jšœ œœœ˜$J˜J˜ Jšœ˜—Jšœ˜—J˜3J˜>J˜ J˜ Jšœ˜—Jšœ œœœ˜%Jšœ˜J˜—J˜šž œœœ&˜>Jšœœ˜Jšœœ%˜4Jšœœ!œ ˜KJ˜šœ œœ˜J˜*J˜Jšœœ ™Jšœ˜—J™Jšœ˜—J˜Jšœ˜J˜šž œœœœœœœœ˜nJ˜ Jšœœ˜ Jšœœ˜ J˜J˜Jšœ œ˜J˜Jšœœ˜J˜0J˜#J˜4J˜!J˜?Jšœœœ˜Jšœ ™ šœœœ˜0Jš œœœ$œœ˜Všœ,œœ˜9Jšœ,œœ˜8—Jšœ:œœ˜FJ˜5Jšœœœœ˜%Jš œœœœ œœ˜8Jšœ œ ˜šœR˜TJšœ˜Jšœ˜—J˜Jšœ˜—Jšœ-™-šœœœ˜'Jšœ"œœ˜.Jšœ"œ œ˜7Jšœ-œœ˜9šœœŸ˜,J˜+šœœœœ˜'J˜Jšœ%œœ˜1Jšœ œœœ˜Jšœœœœ˜:Jšœœ'˜.J˜'J˜=JšœœI˜PJšœ œœ˜Jš œ œœœœ˜(J˜J˜Jšœ˜ ——Jšœ)œœ˜5Jšœœ œœ˜0šœœ˜&Jšœœ˜J˜1Jšœœ˜+J˜Jšœœ ˜&Jšœœœœ˜&Jš œœœ œœ˜0Jšœœ)˜Hšœ6™6Jšœ(™(—šœ˜%J˜J˜ J˜ Jšœ˜Jšœ œœœ˜"Jšœ˜J˜—J˜—…—/–M¢