DIRECTORY Averagers, BasicTime, Buttons, Containers, IO, Labels, Menus, RealFns, Rope, Sliders, ViewerClasses, ViewerOps; AveragersImpl: CEDAR MONITOR LOCKS a USING a: Averager IMPORTS BasicTime, Buttons, Containers, IO, Labels, RealFns, Sliders, ViewerOps EXPORTS Averagers = BEGIN OPEN Averagers; Time: TYPE = BasicTime.GMT; Averager: TYPE = REF AveragerPrivate; AveragerPrivate: PUBLIC TYPE = MONITORED RECORD [ logMin, logMax: INT, min, scale: REAL, halfLife: Seconds, w: REAL, average: REAL, lastTime: Time, container, nameLabel, halfLifeButton, valueShower: Viewer _ NIL ]; logOneHalf: REAL = RealFns.Log[10, 0.5]; halfMaxHalfLife: Seconds = LONG[12*60]*60; sep1: INT _ 1; sep2: INT _ 2; Create: PUBLIC PROC [ viewerInfo: ViewerClasses.ViewerRec _ [], name: ROPE, nameWidth: INT, halfLife: Seconds, logMin, logMax: INT, initialValue: REAL _ 0.0 ] RETURNS [a: Averager] = { a _ NEW [AveragerPrivate _ [ logMin: logMin, logMax: logMax, min: RealFns.Power[10, logMin], scale: 1.0/(logMax - logMin), halfLife: halfLife, w: logOneHalf/halfLife, average: initialValue, lastTime: BasicTime.Now[], container: Containers.Create[viewerInfo] ]]; a.nameLabel _ Labels.Create[info: [parent: a.container, wx: 0, wy: 0, ww: nameWidth, name: name, border: FALSE], paint: FALSE]; a.halfLifeButton _ Buttons.Create[info: [parent: a.container, wx: a.nameLabel.wx+a.nameLabel.ww+sep1, wy: 0, border: FALSE, name: FmtPeriod[a.halfLife]], proc: TweakHalfLife, clientData: a, paint: FALSE]; a.valueShower _ Sliders.Create[info: [parent: a.container, wx: a.halfLifeButton.wx+a.halfLifeButton.ww+sep1, wy: 0, ww: 10, wh: a.container.ch, border: FALSE], orientation: horizontal, value: Normalize[a, initialValue], clientData: a, paint: FALSE]; Containers.ChildXBound[a.container, a.valueShower]; ViewerOps.PaintViewer[a.container, all]; }; Normalize: PROC [a: Averager, value: REAL] RETURNS [normalized: REAL] = INLINE { normalized _ MIN[1.0, MAX[RealFns.Log[10, MAX[a.min, ABS[value]]]-a.logMin, 0] * a.scale]}; TweakHalfLife: PROC [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift, control: BOOL _ FALSE]--Buttons.ButtonProc-- = { a: Averager = NARROW[clientData]; EnterAnd: ENTRY PROC [a: Averager] = { newHalfLife: Seconds = SELECT mouseButton FROM red => MAX[MIN[halfMaxHalfLife, a.halfLife]*2, 1], yellow => a.halfLife, blue => MAX[a.halfLife/2, 1], ENDCASE => ERROR; IF newHalfLife # a.halfLife THEN { a.halfLife _ newHalfLife; a.w _ logOneHalf/a.halfLife; Buttons.ReLabel[a.halfLifeButton, FmtPeriod[a.halfLife]]; }; }; EnterAnd[a]; }; AsViewer: PUBLIC PROC [a: Averager] RETURNS [v: Viewer] = { v _ a.container}; AddSample: PUBLIC ENTRY PROC [a: Averager, amount: REAL] = { ENABLE UNWIND => NULL; now: Time = BasicTime.Now[]; period: Seconds = BasicTime.Period[a.lastTime, now]; keep: REAL = RealFns.Exp[a.w * period]; a.average _ keep*(a.average-amount) + amount; Sliders.SetContents[a.valueShower, Normalize[a, a.average]]; }; FmtPeriod: PROC [period: Seconds] RETURNS [asRope: ROPE] = { hours: INT = period/3600; rem1: INT = period - hours*3600; minutes: INT = rem1 / 60; seconds: INT = rem1 - minutes*60; asRope _ IO.PutFR["%02g:%02g:%02g", [integer[hours]], [integer[minutes]], [integer[seconds]]]; }; END. BAveragersImpl.Mesa Spreitzer, June 16, 1986 6:03:05 pm PDT ΚT– "cedar" style˜code™K™'—K˜KšΟk œ,œB˜yK˜šΟn œœ˜Kšœœ ˜Kšœ!œ%˜OKšœ ˜Kšœ˜—K˜Kšœœ ˜K˜Kšœœ œ˜K˜Kšœ œœ˜%š œœœ œœ˜1Kšœœ˜Kšœ œ˜K˜KšΟgœœ˜Kšœ œ˜Kšœ˜Kšœ<˜?K˜—K˜Kšœ œ˜(Kšœœ ˜*K˜Kšœœ˜Kšœœ˜K˜šœ˜š˜šœ˜K˜)Kšœœ˜ Kšœ œ˜K˜Kšœœ˜Kšœœ˜K˜—Kšœ˜—˜šœœ˜K˜K˜Kšœ˜Kšœ˜K˜KšŸœ˜K˜Kšœ˜Kšœ(˜(K˜—K•StartOfExpansionγ[info: ViewerClasses.ViewerRec _ [class: NIL, wx: 0, wy: 0, ww: 0, wh: 0, cx: 0, cy: 0, cw: 0, ch: 0, lock: [process: PROCESS#0B, count: 0B (0)], tipTable: NIL, name: NIL, file: NIL, label: NIL, menu: NIL, icon: 177777B?, column: left, caption: FALSE, scrollable: TRUE, hscrollable: FALSE, iconic: TRUE, border: TRUE, newVersion: FALSE, newFile: FALSE, visible: TRUE, offDeskTop: FALSE, destroyed: FALSE, init: FALSE, saveInProgress: FALSE, inhibitDestroy: FALSE, guardDestroy: FALSE, paintingWedged: FALSE, spare0: FALSE, spare1: FALSE, spare2: FALSE, spare3: FALSE, spare4: FALSE, spare5: FALSE, spare6: FALSE, position: 0, openHeight: 0, link: NIL, parent: NIL, sibling: NIL, child: NIL, props: NIL, data: NIL], font: ImagerFont.Font _ NIL, paint: BOOL _ TRUE]šœiœ œ˜KšœuœKœ˜ΜKšœ˜œUœ˜ωK˜3K˜(K˜——K˜š ž œœœœœœ˜PKš œ œœœœ#˜[—K˜šž œœ œœœœœ9œœΟcœ˜ŸKšœœ ˜!šžœœœ˜&šœœ ˜.Kšœœœ$˜2Kšœ˜Kšœœ˜Kšœœ˜—šœœ˜"K˜KšœŸœ˜K˜9K˜—K˜—K˜ K˜—K˜šžœœœœ˜;K˜—K˜š ž œœœœœ˜