@cycle/time
Advanced tools
Comparing version 0.9.1 to 0.10.0
@@ -0,1 +1,16 @@ | ||
<a name="0.10.0"></a> | ||
# 0.10.0 (2017-09-04) | ||
### Bug Fixes | ||
* **time:** comparator can return a boolean ([45417b9](https://github.com/cyclejs/cyclejs/commit/45417b9)) | ||
### Features | ||
* **time:** support creating custom operators with Time.createOperator() ([d218064](https://github.com/cyclejs/cyclejs/commit/d218064)) | ||
<a name="0.9.1"></a> | ||
@@ -2,0 +17,0 @@ ## 0.9.1 (2017-08-30) |
import { Stream } from 'most'; | ||
import { Frame } from './src/animation-frames'; | ||
import { Comparator, OperatorArgs } from './src/types'; | ||
declare type Operator = <T>(stream: Stream<T>) => Stream<T>; | ||
@@ -13,5 +14,6 @@ interface TimeSource { | ||
interface MockTimeSource extends TimeSource { | ||
createOperator<T>(): OperatorArgs<T>; | ||
diagram(str: string, values?: Object): Stream<any>; | ||
record(stream: Stream<any>): Stream<Array<any>>; | ||
assertEqual(actual: Stream<any>, expected: Stream<any>): void; | ||
assertEqual(actual: Stream<any>, expected: Stream<any>, comparator?: Comparator): void; | ||
run(cb?: (err?: Error) => void): void; | ||
@@ -18,0 +20,0 @@ } |
import { Observable } from 'rxjs/Observable'; | ||
import 'rxjs/add/observable/from'; | ||
import { Frame } from './src/animation-frames'; | ||
import { Comparator, OperatorArgs } from './src/types'; | ||
declare type Operator = <T>(observable: Observable<T>) => Observable<T>; | ||
interface TimeSource { | ||
createOperator<T>(): OperatorArgs<T>; | ||
animationFrames(): Observable<Frame>; | ||
@@ -16,3 +18,3 @@ delay(delayTime: number): Operator; | ||
record(observable: Observable<any>): Observable<Array<any>>; | ||
assertEqual(actual: Observable<any>, expected: Observable<any>): void; | ||
assertEqual(actual: Observable<any>, expected: Observable<any>, comparator?: Comparator): void; | ||
run(cb?: (err?: Error) => void): void; | ||
@@ -19,0 +21,0 @@ } |
import xs from 'xstream'; | ||
declare function makeDebounce(schedule: any, currentTime: () => number): (debounceInterval: number) => <T>(stream: xs<T>) => xs<T>; | ||
import { OperatorArgs } from './types'; | ||
declare function makeDebounce(createOperator: () => OperatorArgs<any>): (debounceInterval: number) => <T>(stream: xs<T>) => xs<T>; | ||
export { makeDebounce }; |
@@ -20,7 +20,8 @@ import xs from 'xstream'; | ||
complete: function () { | ||
schedule.completion(listener, currentTime()); | ||
schedule.complete(listener, currentTime()); | ||
}, | ||
}; | ||
} | ||
function makeDebounce(schedule, currentTime) { | ||
function makeDebounce(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function debounce(debounceInterval) { | ||
@@ -27,0 +28,0 @@ return function debounceOperator(stream) { |
import xs from 'xstream'; | ||
declare function makeDelay(schedule: any, currentTime: () => number): (delayTime: number) => <T>(stream: xs<T>) => xs<T>; | ||
import { OperatorArgs } from './types'; | ||
declare function makeDelay(createOperator: () => OperatorArgs<any>): (delayTime: number) => <T>(stream: xs<T>) => xs<T>; | ||
export { makeDelay }; |
@@ -13,7 +13,8 @@ import xs from 'xstream'; | ||
complete: function () { | ||
schedule.completion(listener, delayedTime()); | ||
schedule.complete(listener, delayedTime()); | ||
}, | ||
}; | ||
} | ||
function makeDelay(schedule, currentTime) { | ||
function makeDelay(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function delay(delayTime) { | ||
@@ -20,0 +21,0 @@ return function delayOperator(stream) { |
@@ -39,3 +39,3 @@ import { adapt } from '@cycle/run/lib/adapt'; | ||
if (character === '|') { | ||
schedule.completion(stream, timeToSchedule); | ||
schedule.complete(stream, timeToSchedule); | ||
} | ||
@@ -42,0 +42,0 @@ else if (character === '#') { |
@@ -56,2 +56,5 @@ import { makeScheduler } from './scheduler'; | ||
} | ||
function createOperator() { | ||
return { schedule: scheduler.add, currentTime: currentTime }; | ||
} | ||
var timeSource = { | ||
@@ -61,6 +64,6 @@ diagram: makeDiagram(scheduler.add, currentTime, interval, setMaxTime), | ||
assertEqual: makeAssertEqual(function () { return timeSource; }, scheduler.add, currentTime, interval, addAssert), | ||
delay: makeDelay(scheduler.add, currentTime), | ||
debounce: makeDebounce(scheduler.add, currentTime), | ||
periodic: makePeriodic(scheduler.add, currentTime), | ||
throttle: makeThrottle(scheduler.add, currentTime), | ||
delay: makeDelay(createOperator), | ||
debounce: makeDebounce(createOperator), | ||
periodic: makePeriodic(createOperator), | ||
throttle: makeThrottle(createOperator), | ||
animationFrames: function () { return timeSource.periodic(16).map(frame); }, | ||
@@ -77,2 +80,3 @@ throttleAnimation: makeThrottleAnimation(function () { return timeSource; }, scheduler.add, currentTime), | ||
}, | ||
createOperator: createOperator, | ||
_scheduler: scheduler.add, | ||
@@ -79,0 +83,0 @@ _time: currentTime, |
import xs from 'xstream'; | ||
declare function makePeriodic(schedule: any, currentTime: () => number): (period: number) => xs<number>; | ||
import { OperatorArgs } from './types'; | ||
declare function makePeriodic(createOperator: () => OperatorArgs<any>): (period: number) => xs<number>; | ||
export { makePeriodic }; |
import xs from 'xstream'; | ||
import { adapt } from '@cycle/run/lib/adapt'; | ||
function makePeriodic(schedule, currentTime) { | ||
function makePeriodic(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function periodic(period) { | ||
@@ -25,3 +26,3 @@ var stopped = false; | ||
stopped = true; | ||
schedule.completion(producer.listener, currentTime()); | ||
schedule.complete(producer.listener, currentTime()); | ||
}, | ||
@@ -28,0 +29,0 @@ }; |
@@ -1,12 +0,16 @@ | ||
declare function makeScheduler(): { | ||
shiftNextEntry(): any; | ||
import { Listener } from 'xstream'; | ||
export interface Schedule<T> { | ||
shiftNextEntry(): T | undefined; | ||
isEmpty(): boolean; | ||
peek(): any; | ||
add: { | ||
_schedule: () => any[]; | ||
next(stream: any, time: number, value: any, f?: () => void): any; | ||
error(stream: any, time: number, error: any): any; | ||
completion(stream: any, time: number): any; | ||
}; | ||
}; | ||
peek(): T | undefined; | ||
add: Scheduler<T>; | ||
} | ||
export declare type PostEventCallback<T> = (event: any, time: number, schedule: Scheduler<T>, currentTime: () => number) => void; | ||
export interface Scheduler<T> { | ||
_schedule: any; | ||
next(listener: Listener<T>, time: number, value: T, callback?: PostEventCallback<T>): void; | ||
error(listener: Listener<T>, time: number, error: Error): void; | ||
complete(listener: Listener<T>, time: number): void; | ||
} | ||
declare function makeScheduler<T>(): Schedule<T>; | ||
export { makeScheduler }; |
@@ -64,3 +64,3 @@ var makeAccumulator = require('sorted-immutable-list').default; | ||
}, | ||
completion: function (stream, time) { | ||
complete: function (stream, time) { | ||
return scheduleEntry({ | ||
@@ -67,0 +67,0 @@ type: 'complete', |
@@ -29,3 +29,3 @@ import xs from 'xstream'; | ||
frame$.removeListener(animationListener); | ||
schedule.completion(listener, currentTime()); | ||
schedule.complete(listener, currentTime()); | ||
}, | ||
@@ -32,0 +32,0 @@ }); |
import xs from 'xstream'; | ||
declare function makeThrottle(schedule: any, currentTime: () => number): (period: number) => <T>(stream: xs<T>) => xs<T>; | ||
import { OperatorArgs } from './types'; | ||
declare function makeThrottle(createOperator: () => OperatorArgs<any>): (period: number) => <T>(stream: xs<T>) => xs<T>; | ||
export { makeThrottle }; |
@@ -20,7 +20,8 @@ import xs from 'xstream'; | ||
complete: function () { | ||
schedule.completion(listener, currentTime()); | ||
schedule.complete(listener, currentTime()); | ||
}, | ||
}; | ||
} | ||
function makeThrottle(schedule, currentTime) { | ||
function makeThrottle(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function throttle(period) { | ||
@@ -27,0 +28,0 @@ return function throttleOperator(stream) { |
@@ -80,8 +80,11 @@ import { makeScheduler } from './scheduler'; | ||
var _a = runRealtime(scheduler, frameCallbacks, currentTime, setTime), pause = _a.pause, resume = _a.resume; | ||
function createOperator() { | ||
return { schedule: scheduler.add, currentTime: currentTime }; | ||
} | ||
var timeSource = { | ||
animationFrames: makeAnimationFrames(addFrameCallback, currentTime), | ||
delay: makeDelay(scheduler.add, currentTime), | ||
debounce: makeDebounce(scheduler.add, currentTime), | ||
periodic: makePeriodic(scheduler.add, currentTime), | ||
throttle: makeThrottle(scheduler.add, currentTime), | ||
delay: makeDelay(createOperator), | ||
debounce: makeDebounce(createOperator), | ||
periodic: makePeriodic(createOperator), | ||
throttle: makeThrottle(createOperator), | ||
throttleAnimation: makeThrottleAnimation(function () { return timeSource; }, scheduler.add, currentTime), | ||
@@ -96,2 +99,3 @@ _time: currentTime, | ||
}, | ||
createOperator: createOperator, | ||
}; | ||
@@ -98,0 +102,0 @@ return timeSource; |
import { Stream } from 'xstream'; | ||
import { Frame } from './animation-frames'; | ||
import { Comparator, OperatorArgs } from './types'; | ||
export declare type Operator = <T>(stream: Stream<T>) => Stream<T>; | ||
export declare type Comparator = (actual: any, expected: any) => void; | ||
export interface TimeSource { | ||
createOperator<T>(): OperatorArgs<T>; | ||
animationFrames(): Stream<Frame>; | ||
@@ -7,0 +8,0 @@ delay(delayTime: number): Operator; |
import { Stream } from 'most'; | ||
import { Frame } from './src/animation-frames'; | ||
import { Comparator, OperatorArgs } from './src/types'; | ||
declare type Operator = <T>(stream: Stream<T>) => Stream<T>; | ||
@@ -13,5 +14,6 @@ interface TimeSource { | ||
interface MockTimeSource extends TimeSource { | ||
createOperator<T>(): OperatorArgs<T>; | ||
diagram(str: string, values?: Object): Stream<any>; | ||
record(stream: Stream<any>): Stream<Array<any>>; | ||
assertEqual(actual: Stream<any>, expected: Stream<any>): void; | ||
assertEqual(actual: Stream<any>, expected: Stream<any>, comparator?: Comparator): void; | ||
run(cb?: (err?: Error) => void): void; | ||
@@ -18,0 +20,0 @@ } |
import { Observable } from 'rxjs/Observable'; | ||
import 'rxjs/add/observable/from'; | ||
import { Frame } from './src/animation-frames'; | ||
import { Comparator, OperatorArgs } from './src/types'; | ||
declare type Operator = <T>(observable: Observable<T>) => Observable<T>; | ||
interface TimeSource { | ||
createOperator<T>(): OperatorArgs<T>; | ||
animationFrames(): Observable<Frame>; | ||
@@ -16,3 +18,3 @@ delay(delayTime: number): Operator; | ||
record(observable: Observable<any>): Observable<Array<any>>; | ||
assertEqual(actual: Observable<any>, expected: Observable<any>): void; | ||
assertEqual(actual: Observable<any>, expected: Observable<any>, comparator?: Comparator): void; | ||
run(cb?: (err?: Error) => void): void; | ||
@@ -19,0 +21,0 @@ } |
import xs from 'xstream'; | ||
declare function makeDebounce(schedule: any, currentTime: () => number): (debounceInterval: number) => <T>(stream: xs<T>) => xs<T>; | ||
import { OperatorArgs } from './types'; | ||
declare function makeDebounce(createOperator: () => OperatorArgs<any>): (debounceInterval: number) => <T>(stream: xs<T>) => xs<T>; | ||
export { makeDebounce }; |
@@ -22,7 +22,8 @@ "use strict"; | ||
complete: function () { | ||
schedule.completion(listener, currentTime()); | ||
schedule.complete(listener, currentTime()); | ||
}, | ||
}; | ||
} | ||
function makeDebounce(schedule, currentTime) { | ||
function makeDebounce(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function debounce(debounceInterval) { | ||
@@ -29,0 +30,0 @@ return function debounceOperator(stream) { |
import xs from 'xstream'; | ||
declare function makeDelay(schedule: any, currentTime: () => number): (delayTime: number) => <T>(stream: xs<T>) => xs<T>; | ||
import { OperatorArgs } from './types'; | ||
declare function makeDelay(createOperator: () => OperatorArgs<any>): (delayTime: number) => <T>(stream: xs<T>) => xs<T>; | ||
export { makeDelay }; |
@@ -15,7 +15,8 @@ "use strict"; | ||
complete: function () { | ||
schedule.completion(listener, delayedTime()); | ||
schedule.complete(listener, delayedTime()); | ||
}, | ||
}; | ||
} | ||
function makeDelay(schedule, currentTime) { | ||
function makeDelay(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function delay(delayTime) { | ||
@@ -22,0 +23,0 @@ return function delayOperator(stream) { |
@@ -41,3 +41,3 @@ "use strict"; | ||
if (character === '|') { | ||
schedule.completion(stream, timeToSchedule); | ||
schedule.complete(stream, timeToSchedule); | ||
} | ||
@@ -44,0 +44,0 @@ else if (character === '#') { |
@@ -58,2 +58,5 @@ "use strict"; | ||
} | ||
function createOperator() { | ||
return { schedule: scheduler.add, currentTime: currentTime }; | ||
} | ||
var timeSource = { | ||
@@ -63,6 +66,6 @@ diagram: diagram_1.makeDiagram(scheduler.add, currentTime, interval, setMaxTime), | ||
assertEqual: assert_equal_1.makeAssertEqual(function () { return timeSource; }, scheduler.add, currentTime, interval, addAssert), | ||
delay: delay_1.makeDelay(scheduler.add, currentTime), | ||
debounce: debounce_1.makeDebounce(scheduler.add, currentTime), | ||
periodic: periodic_1.makePeriodic(scheduler.add, currentTime), | ||
throttle: throttle_1.makeThrottle(scheduler.add, currentTime), | ||
delay: delay_1.makeDelay(createOperator), | ||
debounce: debounce_1.makeDebounce(createOperator), | ||
periodic: periodic_1.makePeriodic(createOperator), | ||
throttle: throttle_1.makeThrottle(createOperator), | ||
animationFrames: function () { return timeSource.periodic(16).map(frame); }, | ||
@@ -79,2 +82,3 @@ throttleAnimation: throttle_animation_1.makeThrottleAnimation(function () { return timeSource; }, scheduler.add, currentTime), | ||
}, | ||
createOperator: createOperator, | ||
_scheduler: scheduler.add, | ||
@@ -81,0 +85,0 @@ _time: currentTime, |
import xs from 'xstream'; | ||
declare function makePeriodic(schedule: any, currentTime: () => number): (period: number) => xs<number>; | ||
import { OperatorArgs } from './types'; | ||
declare function makePeriodic(createOperator: () => OperatorArgs<any>): (period: number) => xs<number>; | ||
export { makePeriodic }; |
@@ -5,3 +5,4 @@ "use strict"; | ||
var adapt_1 = require("@cycle/run/lib/adapt"); | ||
function makePeriodic(schedule, currentTime) { | ||
function makePeriodic(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function periodic(period) { | ||
@@ -28,3 +29,3 @@ var stopped = false; | ||
stopped = true; | ||
schedule.completion(producer.listener, currentTime()); | ||
schedule.complete(producer.listener, currentTime()); | ||
}, | ||
@@ -31,0 +32,0 @@ }; |
@@ -1,12 +0,16 @@ | ||
declare function makeScheduler(): { | ||
shiftNextEntry(): any; | ||
import { Listener } from 'xstream'; | ||
export interface Schedule<T> { | ||
shiftNextEntry(): T | undefined; | ||
isEmpty(): boolean; | ||
peek(): any; | ||
add: { | ||
_schedule: () => any[]; | ||
next(stream: any, time: number, value: any, f?: () => void): any; | ||
error(stream: any, time: number, error: any): any; | ||
completion(stream: any, time: number): any; | ||
}; | ||
}; | ||
peek(): T | undefined; | ||
add: Scheduler<T>; | ||
} | ||
export declare type PostEventCallback<T> = (event: any, time: number, schedule: Scheduler<T>, currentTime: () => number) => void; | ||
export interface Scheduler<T> { | ||
_schedule: any; | ||
next(listener: Listener<T>, time: number, value: T, callback?: PostEventCallback<T>): void; | ||
error(listener: Listener<T>, time: number, error: Error): void; | ||
complete(listener: Listener<T>, time: number): void; | ||
} | ||
declare function makeScheduler<T>(): Schedule<T>; | ||
export { makeScheduler }; |
@@ -66,3 +66,3 @@ "use strict"; | ||
}, | ||
completion: function (stream, time) { | ||
complete: function (stream, time) { | ||
return scheduleEntry({ | ||
@@ -69,0 +69,0 @@ type: 'complete', |
@@ -31,3 +31,3 @@ "use strict"; | ||
frame$.removeListener(animationListener); | ||
schedule.completion(listener, currentTime()); | ||
schedule.complete(listener, currentTime()); | ||
}, | ||
@@ -34,0 +34,0 @@ }); |
import xs from 'xstream'; | ||
declare function makeThrottle(schedule: any, currentTime: () => number): (period: number) => <T>(stream: xs<T>) => xs<T>; | ||
import { OperatorArgs } from './types'; | ||
declare function makeThrottle(createOperator: () => OperatorArgs<any>): (period: number) => <T>(stream: xs<T>) => xs<T>; | ||
export { makeThrottle }; |
@@ -22,7 +22,8 @@ "use strict"; | ||
complete: function () { | ||
schedule.completion(listener, currentTime()); | ||
schedule.complete(listener, currentTime()); | ||
}, | ||
}; | ||
} | ||
function makeThrottle(schedule, currentTime) { | ||
function makeThrottle(createOperator) { | ||
var _a = createOperator(), schedule = _a.schedule, currentTime = _a.currentTime; | ||
return function throttle(period) { | ||
@@ -29,0 +30,0 @@ return function throttleOperator(stream) { |
@@ -82,8 +82,11 @@ "use strict"; | ||
var _a = runRealtime(scheduler, frameCallbacks, currentTime, setTime), pause = _a.pause, resume = _a.resume; | ||
function createOperator() { | ||
return { schedule: scheduler.add, currentTime: currentTime }; | ||
} | ||
var timeSource = { | ||
animationFrames: animation_frames_1.makeAnimationFrames(addFrameCallback, currentTime), | ||
delay: delay_1.makeDelay(scheduler.add, currentTime), | ||
debounce: debounce_1.makeDebounce(scheduler.add, currentTime), | ||
periodic: periodic_1.makePeriodic(scheduler.add, currentTime), | ||
throttle: throttle_1.makeThrottle(scheduler.add, currentTime), | ||
delay: delay_1.makeDelay(createOperator), | ||
debounce: debounce_1.makeDebounce(createOperator), | ||
periodic: periodic_1.makePeriodic(createOperator), | ||
throttle: throttle_1.makeThrottle(createOperator), | ||
throttleAnimation: throttle_animation_1.makeThrottleAnimation(function () { return timeSource; }, scheduler.add, currentTime), | ||
@@ -98,2 +101,3 @@ _time: currentTime, | ||
}, | ||
createOperator: createOperator, | ||
}; | ||
@@ -100,0 +104,0 @@ return timeSource; |
import { Stream } from 'xstream'; | ||
import { Frame } from './animation-frames'; | ||
import { Comparator, OperatorArgs } from './types'; | ||
export declare type Operator = <T>(stream: Stream<T>) => Stream<T>; | ||
export declare type Comparator = (actual: any, expected: any) => void; | ||
export interface TimeSource { | ||
createOperator<T>(): OperatorArgs<T>; | ||
animationFrames(): Stream<Frame>; | ||
@@ -7,0 +8,0 @@ delay(delayTime: number): Operator; |
{ | ||
"name": "@cycle/time", | ||
"version": "0.9.1", | ||
"version": "0.10.0", | ||
"description": "A time driver designed to enable awesome testing and dev tooling", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -268,2 +268,3 @@ # @cycle/time | ||
## API | ||
@@ -367,2 +368,57 @@ | ||
#### `createOperator()` | ||
Used for creating custom time based operators. Used in conjunction with `xs.create`. | ||
Returns an object with a `schedule` object and `currentTime` function. | ||
The `schedule` is used for adding events to the schedule. It has three methods: | ||
* `next` - takes an xstream `listener`, the `time` the event should be dispatched, and the `event` to dispatch | ||
* `error` - takes an xstream `listener`, the `time` the error should be dispatched, and the `error` to dispatch | ||
* `complete` - takes an xstream `listener` and the completion `time` | ||
The `currentTime` function takes no arguments and returns a number representing the time in milliseconds since the driver started. | ||
Generally you want to schedule relative to `currentTime`. If you schedule an event prior or equal to `currentTime`, it will be executed in the current tick. | ||
Here is an example of a custom operator, `delayBy`, which delays events by a time determined by a selector function. | ||
```js | ||
function delayBy(timeSource, delaySelector) { | ||
return function delayByOperator(stream) { | ||
let sourceListener; | ||
return xs.create({ | ||
start(listener) { | ||
const {schedule, currentTime} = timeSource.createOperator(); | ||
sourceListener = stream.addListener({ | ||
next(t) { | ||
const delay = delaySelector(t); | ||
schedule.next(listener, currentTime() + delay, t); | ||
}, | ||
error(err) { | ||
schedule.error(listener, currentTime(), err); | ||
}, | ||
complete() { | ||
schedule.complete(listener, currentTime()); | ||
}, | ||
}); | ||
}, | ||
stop() { | ||
stream.removeListener(sourceListener); | ||
} | ||
}); | ||
}; | ||
}; | ||
Time.periodic(1000).compose(delayBy(Time, i => i * 100)); | ||
``` | ||
### `mockTimeSource({interval = 20})` | ||
@@ -369,0 +425,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
379120
115
8956
549