import { Timestamp } from "../Types"; import { PMessage, RawID } from "../parse/Types"; import { Message } from "../process/Types"; /** A group of raw parser messages that belong to the same author, in the same channel, in chronological order */ export type PMessageGroup = PMessage[]; /** Function to process a group of messages into Message's */ export type ProcessGroupFn = (group: PMessageGroup) => Message[]; /** * This class handles all the messages in a channel, either processed or not. * Responsible for receiving PMessage objects (parser messages) and generate groups of messages (PMessageGroup) * to be processed into Message's * We want to process messages in groups because it makes more accurate some analysis (e.g. language recognition). * The group of messages generated by this class are sent by the same author, in chronological order. * * We have to deal with messages from different files (exports) that may have different starting times * for the same channel, and even overlapping periods. So this class resolves all that. * We have the concept of intervals, where each interval (a @see MessagesInterval instance) stores messages from * a starting time to an ending time. * * ❗ This class assumes that messages are added in chronological order, unless they are separated by a `markEOF()` call. * This way it can deal with out-of-order (between `markEOF` calls) and duplicated messages. * * If a message with a timestamp that is contained in an existing interval is added (but not previously already), * it will be dropped (not that common, e.g. different exports with deleted messages) * * After all the processing is done, processed messages can be iterated via `*processedMessages()` in the * correct chronological order. * * Note: in the future, we may want to process PMessage into IMessage's (some kind of intermediate messages) instead of * just Message, so we can pass intermediate information not needed for the final Message. This will require * refactoring the MessagesArray class. */ export declare class ChannelMessages { /** All intervals found until now */ private intervals; /** Currently open interval. Next messages will be stored here */ private openInterval?; /** * Adds a PMessage to the pending messages to processed in the current open interval. * If there is no open interval, a new one will be created with the given message. */ addMessage(message: PMessage): void; /** * Mark the end of an input file. This allows the next message added (from another file) * to have a different starting timestamp. * * It will close the current open interval, if any. Make sure to call `process` to process leftover messages. */ markEOF(): void; /** * Process as much pending messages as possible. Not all are processed since the current open interval * may receive more messages from the same author in the future (remember we are grouping them by author). */ process(fn: ProcessGroupFn): void; /** @returns an iterator over the processed messages */ processedMessages(): Generator<{ id: RawID; msg: Message; }, void, unknown>; /** @returns the number of messages in this channel */ get numMessages(): number; } /** * This class represents a list of messages contained in a time interval. * Messages stored here can be either pending to be processed or already processed. (PMessage → Message) * Unprocessed messages (PMessage) are added via `addAndExtend(message)`. Eventually you * should call `process(fn, isClosed)` to process all pending messages (into Message). * The processing is not done by this class; instead you are expected to provide a function to process * groups of messages into Message's. * These groups of messages are PMessageGroup and are guaranteed to be from the same author, in chronological order. * The `isClosed` parameter is used to indicate that the interval is closed and no more messages will be added, to * allow process the leftover. * * It also keeps track of the index of each message by its ID. */ export declare class MessagesInterval { private start; private end; /** Messages pending to be grouped and processed. It should be very few elements here at a time */ private messageQueue; /** Messages already processed. */ private messages; /** Original platform IDs */ private ids; constructor(initialMessage: PMessage); /** Adds the PMessage to the queue and extends the end of the interval to contain it */ addMessageAndExtend(message: PMessage): void; /** * Process all the messages in the queue. * It will group (by author) them in insertion order and call `fn` for each group, * storing the resulting Message as processed messages. * * @param isClosed if true, the interval is considered closed and it won't wait for new messages, thus processing the leftover */ process(fn: ProcessGroupFn, isClosed: boolean): void; /** @returns an iterator over the processed messages */ processedMessages(): Generator<{ id: RawID; msg: Message; }, void, unknown>; isContained(ts: Timestamp): boolean; get startTimestamp(): number; /** @returns the total number of messages in the interval */ get numMessages(): number; }