<commit_before>package peergos.shared.user;

import jsinterop.annotations.*;
import peergos.shared.cbor.*;

import java.time.*;
import java.util.*;

@JsType
public class ServerMessage implements Comparable<ServerMessage>, Cborable {
    public static final int MAX_CONTENT_SIZE = 4096;
    private static final Map<Integer, Type> byValue = new HashMap<>();
    public enum Type {
        FromServer(1),
        FromUser(2),
        Dismiss(3);

        public final int value;
        Type(int value) {
            this.value = value;
            byValue.put(value, this);
        }

        public static Type byValue(int val) {
            if (!byValue.containsKey(val))
                throw new IllegalStateException("Unknown server message type: " + val);
            return byValue.get(val);
        }
    }

    // id is unique to server. Allocated by server.
    // For replies/dismissals this is the id of the message being replied to.
    // For messages from user that aren't replies this is -1.
    @JsIgnore
    public final long id;
    public final Type type;
    @JsIgnore
    public final long sentEpochMillis;
    public final String contents;
    public final Optional<Long> replyToId;
    public final boolean isDismissed;

    public ServerMessage(long id, Type type, long sentEpochMillis, String contents, Optional<Long> replyToId, boolean isDismissed) {
        if (contents.length() > MAX_CONTENT_SIZE)
            throw new IllegalStateException("Message body is longer than maximum allowed size of " + MAX_CONTENT_SIZE + " characters!");
        this.id = id;
        this.type = type;
        this.sentEpochMillis = sentEpochMillis;
        this.contents = contents;
        this.replyToId = replyToId;
        this.isDismissed = isDismissed;
    }


    @JsMethod
    public String getAuthor() {
        return type.name();
    }

    @JsMethod
    public String id() {
        return Long.toString(id);
    }

    @JsMethod
    public String getPreviousMessageId() {
        return replyToId.isPresent() ? replyToId.get().toString() : null;
    }

    @JsMethod
    public String getContents() {
        return contents;
    }

    @JsMethod
    public LocalDateTime getSendTime() {
        return LocalDateTime.ofEpochSecond(sentEpochMillis/1000, (int)(sentEpochMillis % 1000)*1000, ZoneOffset.UTC);
    }

    @Override
    public int compareTo(ServerMessage other) {
        return Long.compare(sentEpochMillis, other.sentEpochMillis);
    }<commit_msg>Add helpful summary() method to ServerMessage<commit_after>package peergos.shared.user;

import jsinterop.annotations.*;
import peergos.shared.cbor.*;

import java.time.*;
import java.util.*;

@JsType
public class ServerMessage implements Comparable<ServerMessage>, Cborable {
    public static final int MAX_CONTENT_SIZE = 4096;
    private static final Map<Integer, Type> byValue = new HashMap<>();
    public enum Type {
        FromServer(1),
        FromUser(2),
        Dismiss(3);

        public final int value;
        Type(int value) {
            this.value = value;
            byValue.put(value, this);
        }

        public static Type byValue(int val) {
            if (!byValue.containsKey(val))
                throw new IllegalStateException("Unknown server message type: " + val);
            return byValue.get(val);
        }
    }

    // id is unique to server. Allocated by server.
    // For replies/dismissals this is the id of the message being replied to.
    // For messages from user that aren't replies this is -1.
    @JsIgnore
    public final long id;
    public final Type type;
    @JsIgnore
    public final long sentEpochMillis;
    public final String contents;
    public final Optional<Long> replyToId;
    public final boolean isDismissed;

    public ServerMessage(long id, Type type, long sentEpochMillis, String contents, Optional<Long> replyToId, boolean isDismissed) {
        if (contents.length() > MAX_CONTENT_SIZE)
            throw new IllegalStateException("Message body is longer than maximum allowed size of " + MAX_CONTENT_SIZE + " characters!");
        this.id = id;
        this.type = type;
        this.sentEpochMillis = sentEpochMillis;
        this.contents = contents;
        this.replyToId = replyToId;
        this.isDismissed = isDismissed;
    }

    public String summary() {
        return "### " + id + ": " + type.name() + " " + getSendTime().toString() + " dismissed:" + isDismissed +
                (replyToId.map(id -> " <==" + id).orElse("")) +
                " body: " + contents.substring(0, Math.min(15, contents.length()));
    }

    @JsMethod
    public String getAuthor() {
        return type.name();
    }

    @JsMethod
    public String id() {
        return Long.toString(id);
    }

    @JsMethod
    public String getPreviousMessageId() {
        return replyToId.isPresent() ? replyToId.get().toString() : null;
    }

    @JsMethod
    public String getContents() {
        return contents;
    }

    @JsMethod
    public LocalDateTime getSendTime() {
        return LocalDateTime.ofEpochSecond(sentEpochMillis/1000, (int)(sentEpochMillis % 1000)*1000, ZoneOffset.UTC);
    }

    @Override
    public int compareTo(ServerMessage other) {
        return Long.compare(sentEpochMillis, other.sentEpochMillis);
    }
{'fraction_non_alphanumeric': 0.0973768635591621, 'fraction_numerical': 0.008114738629930176, 'mean_word_length': 2.5907859078590785, 'pattern_counts': {'":': 1, '<': 14, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2000509', 'n_tokens_mistral': 1532, 'n_tokens_neox': 1482, 'n_words': 426}