<commit_before>"use strict";

var DataSources = {
    frame: {
        fromJson: function(json) {
            return {
                bounds: Bounds.fromAttrs({
                    x: json.x,
                    y: json.y,
                    width: json.w,
                    height: json.h,
                }),
                time: json.frame,
            };
        },

        toJson: function(frame) {
            var attr = Bounds.toAttrs(frame.bounds);
            return {
                x: attr.x,
                y: attr.y,
                w: attr.width,
                h: attr.height,
                frame: frame.time,
            };
        },
    },

    thing: {
        fromJson: function(json) {
            var thing = Thing.newFromCreationRect();
            thing.keyframes = json.keyframes.map(DataSources.frame.fromJson);
            thing.type = json.type;
            return thing;
        },

        toJson: function(thing) {
            return {
                keyframes: thing.keyframes.map(DataSources.frame.toJson),
                type: thing.type,
            };
        },
    },

    annotations: {
        fromJson: function(json) {
            return json.map(DataSources.thing.fromJson);
        },

        toJson: function(things) {
            return things.map(DataSources.thing.toJson);
        },

        load: function(id) {
            return fetch(`/annotation/${id}`, {
                method: 'get'
            }).then((response) => {
                if (!response.ok) {
                    return Promise.reject("DataSources.annotations.load failed: fetch");
                }
                return response.text();
            }).then((text) => {
                var json = (text === '') ? [] : JSON.parse(text);
                var things = DataSources.annotations.fromJson(json);

                return Promise.resolve(things);
            });
        },

        save: function(id, things, mturk) {
            var json = DataSources.annotations.toJson(things);
            return fetch(`/annotation/${id}`, {
                headers: {
                    'X-CSRFToken': window.CSRFToken,
                    'Content-Type': 'application/json',
                },
                credentials: 'same-origin',
                method: 'post',
                body: JSON.stringify(json),
            }).then((response) => {
                if (response.ok) {
                    if (mturk) {
                        $('#turk-form').submit();
                    }
                    return Promise.resolve('State saved successfully.');
                } else {
                    return Promise.resolve(`Error code ${response.status}`);
                }
            });
        }
    },
};

void DataSources;
<commit_msg>Persistent color<commit_after>"use strict";

var DataSources = {
    frame: {
        fromJson: function(json) {
            return {
                bounds: Bounds.fromAttrs({
                    x: json.x,
                    y: json.y,
                    width: json.w,
                    height: json.h,
                }),
                time: json.frame,
            };
        },

        toJson: function(frame) {
            var attr = Bounds.toAttrs(frame.bounds);
            return {
                x: attr.x,
                y: attr.y,
                w: attr.width,
                h: attr.height,
                frame: frame.time,
            };
        },
    },

    thing: {
        fromJson: function(json) {
            var thing = Thing.newFromCreationRect();
            thing.keyframes = json.keyframes.map(DataSources.frame.fromJson);
            thing.type = json.type;
            thing.fill = json.color || Misc.getRandomColor();
            return thing;
        },

        toJson: function(thing) {
            return {
                keyframes: thing.keyframes.map(DataSources.frame.toJson),
                type: thing.type,
                color: thing.fill,
            };
        },
    },

    annotations: {
        fromJson: function(json) {
            return json.map(DataSources.thing.fromJson);
        },

        toJson: function(things) {
            return things.map(DataSources.thing.toJson);
        },

        load: function(id) {
            return fetch(`/annotation/${id}`, {
                method: 'get'
            }).then((response) => {
                if (!response.ok) {
                    return Promise.reject("DataSources.annotations.load failed: fetch");
                }
                return response.text();
            }).then((text) => {
                var json = (text === '') ? [] : JSON.parse(text);
                var things = DataSources.annotations.fromJson(json);

                return Promise.resolve(things);
            });
        },

        save: function(id, things, mturk) {
            var json = DataSources.annotations.toJson(things);
            return fetch(`/annotation/${id}`, {
                headers: {
                    'X-CSRFToken': window.CSRFToken,
                    'Content-Type': 'application/json',
                },
                credentials: 'same-origin',
                method: 'post',
                body: JSON.stringify(json),
            }).then((response) => {
                if (response.ok) {
                    if (mturk) {
                        $('#turk-form').submit();
                    }
                    return Promise.resolve('State saved successfully.');
                } else {
                    return Promise.resolve(`Error code ${response.status}`);
                }
            });
        }
    },
};

void DataSources;

{'fraction_non_alphanumeric': 0.12354394634662902, 'fraction_numerical': 0.0, 'mean_word_length': 1.1280510702215547, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '2622801', 'n_tokens_mistral': 1491, 'n_tokens_neox': 1403, 'n_words': 258}