DIRECTORY IO, Commander USING [ CommandProc, Register ], Convert USING [ IntFromRope ], Lark USING [ bStar, bThorp, CommandEvent, CommandEvents, CommandEventSequence, Device, disabled, DTMFEvent, enabled, endNum, Event, Passel, reset, StatusEvent, StatusEvents, SHHH ], LarkOpsRpcControl, LarkSmarts, Nice, RefID USING [ ID, Reseal ], RPC USING [ CallFailed ], Rope USING [ Concat, FromChar, ROPE ], Process USING [ Detach, MsecToTicks, SetTimeout ], ThPartyPrivate USING [ SmartsData ], ThSmartsPrivate USING [ click, EnterLarkSt, flushMarker, GetSmartsInfo, indexMarkerEnd, LarkInfo, LarkProseQueue, LarkState, maxClientMarker, pResetConfirmEnd, ProseControlDone, proseFailure, ReportProseDone, RingDetState, SmartsInfo, spkrOn, stopAndFlushEnd, SwitchState, TonesDone ], Thrush USING[ ProseSpec, ROPE, SHHH, SmartsID ], ThNet USING [ pd ], VoiceUtils USING [ Report ] ; LarkInImpl: CEDAR MONITOR LOCKS info USING info: LarkInfo IMPORTS LarkOpsRpcControl, Commander, Convert, IO, Nice, Process, RefID, Rope, RPC, ThNet, ThSmartsPrivate, VoiceUtils EXPORTS LarkSmarts, ThSmartsPrivate= { OPEN IO; Reseal: PROC[r: REF] RETURNS[RefID.ID] = INLINE {RETURN[RefID.Reseal[r]]; }; LarkInfo: TYPE = ThSmartsPrivate.LarkInfo; RingDetState: TYPE = ThSmartsPrivate.RingDetState; SmartsData: TYPE = ThPartyPrivate.SmartsData; SmartsInfo: TYPE = ThSmartsPrivate.SmartsInfo; SmartsID: TYPE = Thrush.SmartsID; SwitchState: TYPE = ThSmartsPrivate.SwitchState; ROPE: TYPE = Thrush.ROPE; bStar: Lark.Event = Lark.bStar; bThorp: Lark.Event = Lark.bThorp; enabled: Lark.Event = Lark.enabled; endNum: Lark.Event = Lark.endNum; disabled: Lark.Event = Lark.disabled; reset: Lark.Event = Lark.reset; PD: TYPE = RECORD [ callTimeoutOK: BOOL_FALSE, -- set to keep Thrush alive when debugging a Lark. debounceInterval: INTEGER _ 300, -- ms. spClickInterval: INTEGER _ 300, breakInterval: INTEGER _ 4500 -- ms., 4 sec. nominal, 500 ms. benefit of doubt ]; pd: REF PD _ NEW[PD_[]]; DebEvent: PROC[info: SmartsInfo, ev: Lark.StatusEvent] = INLINE { s: IO.STREAM=IO.ROS[]; s.PutF["[%3B, %3B, ", card[LONG[ IF info#NIL THEN LOOPHOLE[info.larkInfo.netAddress.host,CARDINAL] ELSE LOOPHOLE[777B, CARDINAL]]], card[LONG[LOOPHOLE[ev.device, CARDINAL]]]]; IF ev.event<='z THEN s.PutF["%g] ",char[ev.event]] ELSE s.PutF["<%3B>] ", card[LONG[LOOPHOLE[ev.event, CARDINAL]]]]; VoiceUtils.Report[s.RopeFromROS[], $LarkDetailed, info.larkInfo]; }; crowbar: BOOL_FALSE; -- TRUE to check basic RPC performance from Lark. RecordEvent: PUBLIC PROC[shh: Thrush.SHHH, smartsID: Thrush.SmartsID, whatHappened: Lark.StatusEvents] RETURNS [ success: BOOL_TRUE ] = { smartsInfo: SmartsInfo = ThSmartsPrivate.GetSmartsInfo[smartsID: smartsID]; parseInfo: SmartsInfo _ smartsInfo; info: LarkInfo; parseSmartsID: SmartsID; IF smartsInfo=NIL OR (info _ smartsInfo.larkInfo)=NIL THEN RETURN[FALSE]; parseSmartsID _ smartsInfo.smartsID; FOR i: Lark.Passel IN [0 .. whatHappened.length) DO sEvent: Lark.StatusEvent _ whatHappened[i]; IF ThNet.pd.debug THEN DebEvent[smartsInfo, sEvent]; IF crowbar OR info.larkState=failed OR info.larkState=recovering THEN LOOP; SELECT sEvent.device FROM ringDetect => { parseSmartsID _ smartsInfo.otherSmartsID; parseInfo _ ThSmartsPrivate.GetSmartsInfo[smartsID: parseSmartsID]; }; tones => { ThSmartsPrivate.TonesDone[smartsInfo.larkInfo, sEvent]; LOOP; }; ENDCASE; SELECT sEvent.device FROM speakerSwitch => sEvent _ InterpretSpeakerSwitch[info, sEvent]; ringDetect => sEvent _ InterpretRingDetect[info, sEvent]; touchPad => { IF sEvent.event=disabled THEN sEvent.event _ smartsInfo.lastTouchpadChar ELSE { smartsInfo.lastTouchpadChar _ sEvent.event; LOOP; -- down transitions of DTMF pad. }; IF sEvent.event='\000 THEN LOOP; }; keyboard => { IF info.textToSpeech THEN HandleAndReport[info, sEvent, smartsInfo]; LOOP; }; hookSwitch => NULL; ENDCASE => ERROR; IF sEvent.device=nothing THEN LOOP; parseInfo.ParseEvent[ smartsInfo: parseInfo, sEvent: sEvent ]; ENDLOOP; }; EventRope: PUBLIC PROC[ shh: Thrush.SHHH, smartsID: SmartsID, time: CARDINAL, device: Lark.Device, events: ROPE] RETURNS[success: BOOL] = { NULL; }; HandleProseOutput: ENTRY PROC[info: LarkInfo, commandEvent: Lark.StatusEvent, sInfo: SmartsInfo] RETURNS [pS: Thrush.ProseSpec _ NIL] = { c: CHAR _ commandEvent.event; SELECT c FROM IO.BEL => NULL; -- take some error action? IO.ESC => info.proseResponse _ ""; -- start of some response '[ => NULL; -- peel this character off ThSmartsPrivate.stopAndFlushEnd => { ThSmartsPrivate.ProseControlDone[info, ThSmartsPrivate.flushMarker]; info.flushJustFinished _ TRUE; }; ThSmartsPrivate.indexMarkerEnd => { marker: INT _ Convert.IntFromRope[info.proseResponse]; IF marker > ThSmartsPrivate.maxClientMarker THEN ThSmartsPrivate.ProseControlDone[info, marker] ELSE { pQ: ThSmartsPrivate.LarkProseQueue _ info.proseQueue; IF pQ=NIL THEN ERROR; IF info.flushJustFinished THEN { FOR pSkip: ThSmartsPrivate.LarkProseQueue _ pQ, pSkip.rest WHILE pSkip#NIL DO IF pSkip.first.proseMarker = marker THEN pQ _ pSkip; ENDLOOP; info.flushJustFinished _ FALSE; }; IF pQ.first.proseMarker = marker THEN { pS _ pQ.first.proseSpec; info.proseQueue _ pQ.rest; -- Flush any skipped items. IF info.proseQueue=NIL THEN info.pTail _ NIL; } ELSE ThSmartsPrivate.ProseControlDone[info, ThSmartsPrivate.proseFailure]; -- fail!!! }; }; ThSmartsPrivate.pResetConfirmEnd => { IF Convert.IntFromRope[info.proseResponse] # 0 THEN ThSmartsPrivate.ProseControlDone[info, ThSmartsPrivate.proseFailure] -- fail!!!; ELSE { ThSmartsPrivate.ProseControlDone[info, ThSmartsPrivate.flushMarker]; info.flushJustFinished _ TRUE; }; }; ENDCASE => info.proseResponse _ Rope.Concat[info.proseResponse, Rope.FromChar[c]]; }; HandleAndReport: PROC [info: LarkInfo, commandEvent: Lark.StatusEvent, sInfo: SmartsInfo] ~ { pS: Thrush.ProseSpec _ HandleProseOutput[info, commandEvent, sInfo]; IF pS#NIL THEN ThSmartsPrivate.ReportProseDone[sInfo, pS]; }; InterpretSpeakerSwitch: ENTRY PROC[info: LarkInfo, sEvent: Lark.StatusEvent] RETURNS [ processedEvent: Lark.StatusEvent] = { interval: INTEGER = LOOPHOLE[sEvent.time-info.swOnTime]; processedEvent _ sEvent; info.swOnTime _ sEvent.time; SELECT sEvent.event FROM enabled => { TRUSTED { Process.Detach[FORK SpeakerSwitchTimeout[info, info.swOnTime]]; }; processedEvent.device _ nothing; RETURN; }; disabled => IF interval >= 0 AND interval <= pd.spClickInterval THEN processedEvent.event _ ThSmartsPrivate.click; ThSmartsPrivate.spkrOn => RETURN; -- a timed-out ON event, which is now being reported ENDCASE => ERROR; }; SpeakerSwitchTimeout: PROC[info: LarkInfo, onTime: CARDINAL] = { SSTE: ENTRY PROC[info: LarkInfo, onTime: CARDINAL] RETURNS [doIt: BOOL] = TRUSTED { wait: CONDITION; Process.SetTimeout[@wait, Process.MsecToTicks[pd.spClickInterval]]; WAIT wait; RETURN[onTime=info.swOnTime]; }; IF ~SSTE[info, onTime] THEN RETURN; -- click happened or something, forget it. info.larkSmartsInfo.ParseEvent[info.larkSmartsInfo, [onTime+pd.spClickInterval, speakerSwitch, ThSmartsPrivate.spkrOn ] ]; }; InterpretRingDetect: ENTRY PROC[info: LarkInfo, sEvent: Lark.StatusEvent] RETURNS [ processedEvent: Lark.StatusEvent _ [ 0, nothing, Lark.reset ] ] = { ENABLE UNWIND=>NULL; interval: INTEGER = LOOPHOLE[sEvent.time-info.ringChangeTime]; event: Lark.Event = sEvent.event; timeout: BOOL _ FALSE; info.ringChangeTime _ sEvent.time; SELECT event FROM enabled => SELECT info.ringDetState FROM idle, between=>NULL; ENDCASE=>RETURN; disabled => SELECT info.ringDetState FROM idle, between=>RETURN; ENDCASE; ENDCASE=>RETURN; SELECT info.ringDetState FROM idle => info.ringDetState _ maybe; between => { info.ringDetState _ ring; processedEvent _ sEvent; }; -- generate new offhook maybe => IF interval info.ringDetState _ between; ENDCASE; info.ringDetInstance _ info.ringDetInstance+1; BROADCAST info.ringDetCondition; -- earlier timeouts zap themselves. IF info.ringDetState = $idle THEN RETURN; TRUSTED { Process.Detach[FORK RingTimeout[info, info.ringDetInstance]]; }; }; RingTimeout: PROC[info: LarkInfo, instance: INT] = { RTEntry: ENTRY PROC[info: LarkInfo] RETURNS[event: Lark.Event_reset] = TRUSTED { -- Process is unsafe ENABLE UNWIND=>NULL; timeout: INTEGER _ pd.breakInterval; IF instance#info.ringDetInstance THEN RETURN; SELECT info.ringDetState FROM $idle => RETURN; $maybe => timeout _ pd.debounceInterval; ENDCASE; Process.SetTimeout[@info.ringDetCondition, Process.MsecToTicks[timeout]]; WAIT info.ringDetCondition; IF info.ringDetInstance#instance THEN RETURN; -- events intervened SELECT info.ringDetState FROM -- timed out $idle => RETURN; -- ?? $maybe => { event _ enabled; info.ringDetState _ $ring; }; -- now ringing ENDCASE => { event _ disabled; info.ringDetState _ $idle; }; -- too long }; event: Lark.Event _ RTEntry[info]; IF event # reset THEN info.larkTrunkSmartsInfo.ParseEvent[ info.larkTrunkSmartsInfo, [info.ringChangeTime, ringDetect, event ] ]; IF event = enabled THEN RingTimeout[info, instance]; -- wait for no-longer-ringing timeout }; InterpretHookState: PUBLIC ENTRY PROC [ info: LarkInfo, rawEvent: Lark.StatusEvent, sInfo: SmartsInfo ] RETURNS [ processedEvent: Lark.StatusEvent ] = { ENABLE UNWIND=>NULL; event: Lark.Event = rawEvent.event; ev: EvType; newState: SwitchState; oldState: SwitchState_info.switchState; ev _ SELECT rawEvent.device FROM hookSwitch => SELECT event FROM Lark.enabled => tsOn, Lark.disabled => tsOff, ENDCASE=> spNone, speakerSwitch => SELECT event FROM ThSmartsPrivate.spkrOn => spOn, Lark.disabled => spOff, ThSmartsPrivate.click => spClick, ENDCASE => spNone, ENDCASE => spNone; processedEvent _ rawEvent; IF ev = spNone THEN { processedEvent.event _ SELECT rawEvent.device FROM touchPad => SELECT event FROM bThorp => endNum, bStar => '*, IN Lark.DTMFEvent => event - (FIRST[Lark.DTMFEvent]-'0), ENDCASE=>event, ENDCASE => event; RETURN; }; newState _ newStates[oldState][ev]; info.switchState _ newState; processedEvent.device _ hookSwitch; IF newState=oldState THEN processedEvent.device_nothing -- no op? ELSE IF newState = $onhook THEN processedEvent.event _ disabled -- really going onhook ELSE { IF oldState = $onhook THEN processedEvent.event _ enabled -- really going offhook ELSE processedEvent.device_nothing; ThSmartsPrivate.EnterLarkSt[info, info.larkState]; }; }; CheckHookState: PUBLIC ENTRY PROC [info: LarkInfo ] RETURNS [ onHook: BOOL_TRUE ] = { ENABLE RPC.CallFailed => IF pd.callTimeoutOK THEN RESUME ELSE GOTO Failed; reverted, wasReverted: BOOL_FALSE; which: CARDINAL; DO which_0; reverted _ FALSE; DO events: Lark.StatusEvents; [which, events] _ info.interface.WhatIsStatus[info.shh, which]; FOR i: NAT IN [0..events.length) DO SELECT events[i].event FROM enabled => SELECT events[i].device FROM hookSwitch => { onHook_FALSE; info.interface.Commands[shh: info.shh, events: assertARelay]; }; revertHookswitch => IF ~wasReverted THEN reverted _ wasReverted _ TRUE; ENDCASE; ENDCASE; ENDLOOP; IF which=0 THEN EXIT; ENDLOOP; IF reverted THEN { info.interface.Commands[shh: info.shh, events: unRevHS]; LOOP; }; EXIT; ENDLOOP; EXITS Failed => onHook_FALSE; }; EvType: TYPE = { tsOff, tsOn, spOff, spOn, spClick, spNone }; newStates: ARRAY SwitchState OF ARRAY EvType OF SwitchState _ [ [ $onhook, $telset, $onhook, $sPEAKER, $speaker, $onhook ], -- onhook [ $onhook, $telset, $telset, $mONITOR, $monitor, $telset ], -- telset [ $speaker, $telset, $onhook, $sPEAKER, $onhook, $speaker ], -- speaker [ $sPEAKER, $mONITOR, $onhook, $sPEAKER, $onhook, $sPEAKER ], -- sPEAKER [ $speaker, $monitor, $telset, $mONITOR, $telset, $monitor ], -- monitor [ $sPEAKER, $mONITOR, $telset, $mONITOR, $telset, $mONITOR ] -- mONITOR ]; ViewCmd: Commander.CommandProc = TRUSTED { Nice.View[pd, "Lark In PD"]; }; unRevHS: Lark.CommandEvents _ NEW[Lark.CommandEventSequence[1]]; assertARelay: Lark.CommandEvents _ NEW[Lark.CommandEventSequence[1]]; unRevHS[0] _ [revertHookswitch, disabled]; assertARelay[0] _ [aRelay, enabled]; Commander.Register["VuLarkIn", ViewCmd, "Program Management variables for Lark Input"]; }. LLarkInImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Last modified by D. Swinehart, May 25, 1986 10:10:22 pm PDT Polle Zellweger (PTZ) August 29, 1985 5:46:32 pm PDT ***************** External Procedures ******************** Handles smarts-independent filtering, events that need timing. Interpret event, possibly filter some out. React to upstrokes, not downstrokes. 0-key Rollover is a side-effect. Try it. Only pass on index marker notifications. Swallow or handle all others. Assume Prose XON / XOFF disabled. Assume only get the following responses: On pReset: pResetConfirmOK if everything's okay cmdLeader <0-16> pResetConfirmEnd otherwise Index marker response: Undetermined problem: BEL It's okay to skip ahead in the queue. Except for 1st item in a conversation, which follows an initial RESET, should be to some entry with queueIt=FALSE. Don't report skipped entries as finished; FinchSmarts will take care of skipping ahead in its queue. (May want to add a proseSpec.type = flushed?) Avoid deadlock - shouldn't call Smarts-level entry procs while holding the LarkIn/Out lock. Generates one "enabled" for every ring detect (with a delay for possible glitches the first time), and a single "disabled" when the last ring has been gone too long. See ThSmartsPrivate.LarkInfo. Bold states occur only when event is enabled, others only when disabled ELSE: The debounce timeout will soon occur and generate the offhook event Filters only events whose device codes are hookswitch and speakerSwitch Implements another state machine via SELECT Translate characters from various devices into common set When newState is onhook, the lark state will soon be idle, and this is just a distraction. Determine if either of telset or speakerphone is activated. Assert aRelay and unrevert hookswitch SwitchState: TYPE = { onhook, telset, speaker, sPEAKER, monitor, mONITOR }; spOn is transition away from middle on speaker switch that lasts more than a few hundred ms. spOff is transition to middle when spOn. spClick is transition away from and back to middle after a few hundred ms. Note: spNone is used to indicate that no interesting action took place. See ThSmartsPrivate.SwitchState for the legal state transitions; others are made harmless here. Scenario: user picks up telset and talks for a while, then clicks the speaker switch; the speaker comes on but the telset is still active. Hanging up switches to $speaker mode; picking up the telset reverts to $telset mode, whence hanging up would terminate the conversation unless the user clicks the switch again. Scenario: user picks up telset and talks for a while, then turns on the speaker switch; the speaker comes on but the telset is still active. Hanging up switches to $sPEAKER mode; picking up the telset reverts to $mONITOR mode, and hanging up alternates back to sPEAKER mode, since the switch is still on. When calls are terminated from Finch or the other party, the terminal state goes $onhook anyhow, so the distinctions between switch-on modes and click modes are not as great as they once were. Swinehart, August 6, 1985 12:10:40 pm PDT Incorporate PTZ changes changes to: DIRECTORY, LarkInImpl, RecordEvent, HandleProseOutput, InterpretSpeakerSwitch Polle Zellweger (PTZ) August 7, 1985 6:36:35 pm PDT Comments only. changes to: EvType, newStates Polle Zellweger (PTZ) August 22, 1985 5:20:05 pm PDT Handle Prose flushing; remove deadlock from HandleProseOutput. changes to: DIRECTORY, RecordEvent, HandleProseOutput, HandleAndReport Polle Zellweger (PTZ) August 23, 1985 2:10:02 pm PDT Input events from the Prose Lark are being interpreted as smarts-level parseable events. Raise error for odd devices. changes to: RecordEvent Polle Zellweger (PTZ) August 23, 1985 2:34:28 pm PDT changes to: RecordEvent, HandleProseOutput Polle Zellweger (PTZ) August 27, 1985 8:57:45 pm PDT Allow for Prose Reset command. changes to: DIRECTORY, HandleProseOutput Polle Zellweger (PTZ) August 29, 1985 5:46:33 pm PDT changes to: HandleProseOutput Swinehart, October 28, 1985 11:54:20 am PST Handle => ID, Log => VoiceUtils changes to: DIRECTORY, LarkInImpl, Reseal, SmartsID, RecordEvent, EventRope, HandleProseOutput, InterpretSpeakerSwitch, InterpretRingDetect, RingDetProc, InterpretHookState, ProblemBool Swinehart, November 29, 1985 11:17:56 am PST When going on hook, don't react to changes in terminal type, since the terminal will soon be put idle by other actions. changes to: InterpretHookState Swinehart, April 10, 1986 11:55:03 am PST Simplify and improve speaker and telset switch handling, add monitor mode as first-class citizen changes to: DIRECTORY, Reseal, SmartsID, SwitchState, ROPE, PD, InterpretSpeakerSwitch, SpeakerSwitchTimeout, SSTE (local of SpeakerSwitchTimeout), InterpretHookState, EvType, newStates Swinehart, May 25, 1986 10:10:16 pm PDT Lark => LarkOps changes to: DIRECTORY, LarkInImpl Ê󘚜™Icodešœ Ïmœ7™BJšœ;™;K™4—J˜šÏk ˜ Jšžœ˜Jšœ žœ˜*Jšœžœ˜Jšœžœ¤žœ˜µJ˜J˜ J˜Jšœžœžœ ˜Jšžœžœ˜Jšœžœžœ˜&Jšœžœ%˜2Jšœžœ˜$šœžœ˜Jšœ…˜…—Jšœžœ žœžœ ˜0Jšœžœ˜Jšœ žœ ˜J˜J˜—šœ ž œžœžœ˜9šž˜Jšœ'žœžœ$˜n—Jšžœ˜&—Jšžœžœ˜J˜JšÏnœžœžœžœžœžœžœ˜LJšœ žœ˜*J˜2Jšœ žœ˜-Jšœ žœ˜.Jšœ žœ˜!Jšœ žœ˜0Jšžœžœ žœ˜J˜J˜!Jšœ#˜#J˜!Jšœ%˜%J˜J˜šžœžœžœ˜JšœžœžœÏc2˜MJšœžœ ˜'Jšœžœ˜Jšœžœ 0˜NJ˜—Jš œžœžœžœžœ˜J˜Jšœ=™=J˜J˜šŸœžœ+žœ˜AJš œžœžœžœžœ˜šœ˜šœžœ˜ Jš žœžœžœžœžœ˜AJšžœžœžœ˜ —Jšœžœžœ žœ˜,—Jšžœžœ˜3Jšžœžœžœ žœ˜BJšœA˜AJšœ˜—J˜Jšœ žœžœ 1˜FšŸ œžœžœž œ=˜fJšžœ ž œ˜J™>Jšœ˜JšœK˜KJšœ#˜#Jšœ˜J˜Jšžœ žœžœžœžœžœžœ˜IJ˜$šžœžœž˜3J˜+Jšžœžœ˜4Jš žœ žœžœžœžœ˜KJ™*šžœž˜šœ˜J˜)JšœC˜CJ˜—šœ ˜ Jšœ7˜7Jšžœ˜J˜—Jšžœ˜—šžœž˜J˜?Jšœ9˜9šœ ˜ J™OJšžœžœ+˜Hšžœ˜Jšœ,žœ  ˜RJ˜—Jšžœžœžœ˜ J˜—šœ ˜ Kšžœžœ+˜DKšžœ˜K˜—Jšœžœ˜Jšžœžœ˜—Jšžœžœžœ˜#Jšœ>˜>Jšžœ˜ ——J˜šŸ œž œ˜Jšœ žœžœžœ˜XJšžœ žœ˜Jšžœ˜Jšœ˜—J˜Jšœ«ž™®š ŸœžœžœDžœžœ˜‰Jšœžœ˜šžœž˜ Jšžœžœ ˜*Jšžœžœ ˜J˜!Jšœ žœžœ˜J˜"šžœžœ˜Jš œ žœžœžœžœžœ˜NJš œ žœžœžœžœ˜IJšžœžœ˜—šžœž˜JšœG™GJšÏbœ˜"Jš¡œ< ˜Zš œ žœžœžœžœ˜QJšžœE™I—Jšœ$˜$Jšžœ˜—J˜.Jšž œ;˜DJšžœžœžœ˜)Jšžœžœ-˜JJšœ˜—J˜J˜šŸ œžœžœ˜4š Ÿœžœžœžœžœ ˜eJšžœžœžœ˜Jšœ žœ˜$Jšžœžœžœ˜-šžœž˜Jšœ žœ˜Jšœ(˜(Jšžœ˜—JšœI˜IJšžœ˜Jšžœžœžœ ˜Bšžœžœ  ˜*Jšœ žœ ˜Jšœ; ˜IJšžœ6  ˜H—J˜—Jšœ"˜"šžœž˜šœ$˜$JšœF˜F——Jšžœžœ %˜ZJšœ˜J˜—šŸœžœžœž˜%šœA˜AJšžœ)˜0—Jšœ+¡ œ¡ ™GJšœ%¡™+Jšžœžœžœ˜J˜#J˜ J˜J˜'šœžœž˜ šœžœž˜Jšœ˜Jšœ˜Jšžœ ˜—šœžœž˜"Jšœ˜Jšœ˜Jšœ!˜!Jšžœ ˜—Jšžœ ˜—J˜šžœ žœ˜J™9šœžœž˜2šœ žœž˜J˜J˜ Jšžœžœ˜8Jšžœ˜—Jšžœ ˜—Jšžœ˜šœ˜J˜——Jšœ#˜#Jšœ˜J˜#Jšžœžœ  ˜AJšžœžœžœ! ˜VJ™Zšžœž˜šžœžœ  ˜QJšžœ˜#—Jšœ2˜2J˜—Jšœ˜—J˜J˜šŸœžœžœž˜!Jšœžœ žœžœ˜3J™;Jšžœžœžœžœžœžœžœ˜JJšœžœžœ˜"Jšœžœ˜šž˜J˜Jšœ žœ˜šž˜J˜J˜?šžœžœžœž˜#šžœž˜šœ žœž˜'šœ˜Jšœžœ˜ Jšœ=˜=J˜—Jšœžœžœžœ˜GJšžœ˜—Jšžœ˜—Jšžœ˜—Jšžœ žœžœ˜Jšžœ˜—šžœ žœ˜J™%Jšœ8˜8Jšžœ˜J˜—Jšžœ˜Jšžœ˜—šž˜Jšœžœ˜—J˜J˜—Jšœ žœ:™KJ™šœžœ1˜=J™\J™(J™JJ™G—J™š Ïf Ðfk¢ £¢£¢£¢˜?J™_Jš¢@Ðcf ˜IJš¢@¤ ˜IJš¢@¤ ˜JJš¢@¤ ˜JJš¢@¤ ˜JJš¢@¤ ˜JJ˜Jš ¼™¼Jš ¦œ )œ )œ $™±J™À—J˜šœ!žœ˜*J˜Jšœ˜J˜—Jšœžœ˜@Jšœ#žœ˜EJšœ*˜*Jšœ$˜$J˜JšœW˜WJ˜™)K™Kšœ ÏrM™Y—™3K™Kšœ ¥™—™4Kšœ>™>Kšœ ¥:™F—™4K™vKšœ ¥ ™—™4Kšœ ¥™*—™4K™Kšœ ¥™(—™4Kšœ ¥™—™+K™Kšœ ¥­™¹—™,K™wKšœ ¥™—™)K™`Kšœ ¥fœ ¥'™¹—™'K™Kšœ ¥™!—K™—…—/BQ