<commit_before>(function ($) {
    function Person(data) {
        _.extend(this, data);
    }
    _.extend(Person.prototype, {

        age: function (date) {
            var birth = this.birth_date;
            if (typeof birth == 'number' || /^c/.test(birth)) {
                birth += '-07-01';
                birth = birth.replace(/^c\s+/, '');
            }
            return moment(date).diff(moment(birth, 'YYYY-MM-DD'), 'd') / 365.2425;
        },

        experience: function (date, pattern) {
            var ymd = moment(date).format('YYYY-MM-DD'),
                regexp = new RegExp(pattern),
                days = 0;
            this.positions.forEach(function (p) {
                if (p.start <= ymd && regexp.test(p.office)) {
                    var end = p.end <= ymd ? moment(p.end, 'YYYY-MM-DD') : moment(date);
                    days += end.diff(moment(p.start, 'YYYY-MM-DD'), 'd');
                }
            });
            return days / 365.2425;
        },

        councilExperience: function (date) {
            return this.experience(date, 'Council');
        },

        mayoralExperience: function (date) {
            return this.experience(date, 'Mayor');
        }
    });

    function Council() {
        _.extend(this, {
            members: [],
            add: [],
            remove: []
        });
    }
    _.extend(Council.prototype, {

        genderCount: function (gender) {
            return this.members.reduce(function (previousValue, currentPerson) {
                if (currentPerson.gender == gender) {
                    previousValue++;
                }
                return previousValue;
            }, 0);
        },

        women: function () {
            return this.genderCount('F');
        },

        men: function () {
            return this.genderCount('M');
        },

        ages: function (date) {
            return this.members.map(function (person) {
                return person.age(date);
            });
        },

        averageAge: function (date) {
            return this.ages(date).reduce(function (previous, current) {
                    return previous + current;
                }, 0) / this.members.length;
        },

        minAge: function (date) {
            return _.min(this.ages(date));
        },

        maxAge: function (date) {
            return _.max(this.ages(date));
        },

        totalCouncilExperience: function (date) {
            return this.members.reduce(function (previousValue, currentPerson) {
                return previousValue + currentPerson.councilExperience(date);
            }, 0);
        },

        totalMayoralExperience: function (date) {
            return this.members.reduce(function (previousValue, currentPerson) {
                return previousValue + currentPerson.mayoralExperience(date);
            }, 0);
        },

        changes: function () {
            var texts = [];
            if (this.remove.length) {
                texts.push('Lost ' + _.pluck(this.remove, 'name').join(', ') + '.');
            }
            if (this.add.length) {
                texts.push('Gained ' + _.pluck(this.add, 'name').join(', ') + '.');
            }
            return texts.join('<br/>');
        }
    });

    $.getJSON('data/person.json', process);

    function process(personData) {
        var councils = {},
            members = [];
        _.each(personData, function (data) {
            var person = new Person(data);
            person.positions.forEach(function (p) {
                if (!/Council/.test(p.office)) {
                    return;
                }
                if (p.start) {
                    if (!councils[p.start]) {
                        councils[p.start] = new Council();
                        councils[p.start].date = p.start;
                    }
                    councils[p.start].add.push(person);
                }
                else {
                    throw 'Missing start in ' + person.code;
                }
                if (p.end) {
                    if (!councils[p.end]) {
                        councils[p.end] = new Council();
                        councils[p.end].date = p.end;<commit_msg>avoid losing and gaining the same person when they're elected to a different seat<commit_after>(function ($) {
    function Person(data) {
        _.extend(this, data);
    }
    _.extend(Person.prototype, {

        age: function (date) {
            var birth = this.birth_date;
            if (typeof birth == 'number' || /^c/.test(birth)) {
                birth += '-07-01';
                birth = birth.replace(/^c\s+/, '');
            }
            return moment(date).diff(moment(birth, 'YYYY-MM-DD'), 'd') / 365.2425;
        },

        experience: function (date, pattern) {
            var ymd = moment(date).format('YYYY-MM-DD'),
                regexp = new RegExp(pattern),
                days = 0;
            this.positions.forEach(function (p) {
                if (p.start <= ymd && regexp.test(p.office)) {
                    var end = p.end <= ymd ? moment(p.end, 'YYYY-MM-DD') : moment(date);
                    days += end.diff(moment(p.start, 'YYYY-MM-DD'), 'd');
                }
            });
            return days / 365.2425;
        },

        councilExperience: function (date) {
            return this.experience(date, 'Council');
        },

        mayoralExperience: function (date) {
            return this.experience(date, 'Mayor');
        }
    });

    function Council() {
        _.extend(this, {
            members: [],
            add: [],
            remove: []
        });
    }
    _.extend(Council.prototype, {

        genderCount: function (gender) {
            return this.members.reduce(function (previousValue, currentPerson) {
                if (currentPerson.gender == gender) {
                    previousValue++;
                }
                return previousValue;
            }, 0);
        },

        women: function () {
            return this.genderCount('F');
        },

        men: function () {
            return this.genderCount('M');
        },

        ages: function (date) {
            return this.members.map(function (person) {
                return person.age(date);
            });
        },

        averageAge: function (date) {
            return this.ages(date).reduce(function (previous, current) {
                    return previous + current;
                }, 0) / this.members.length;
        },

        minAge: function (date) {
            return _.min(this.ages(date));
        },

        maxAge: function (date) {
            return _.max(this.ages(date));
        },

        totalCouncilExperience: function (date) {
            return this.members.reduce(function (previousValue, currentPerson) {
                return previousValue + currentPerson.councilExperience(date);
            }, 0);
        },

        totalMayoralExperience: function (date) {
            return this.members.reduce(function (previousValue, currentPerson) {
                return previousValue + currentPerson.mayoralExperience(date);
            }, 0);
        },

        changes: function () {
            var texts = [],
                lost = _.difference(this.remove, this.add),
                gained = _.difference(this.add, this.remove);
            if (lost.length) {
                texts.push('Lost ' + _.pluck(lost, 'name').join(', ') + '.');
            }
            if (gained.length) {
                texts.push('Gained ' + _.pluck(gained, 'name').join(', ') + '.');
            }
            return texts.join('<br/>');
        }
    });

    $.getJSON('data/person.json', process);

    function process(personData) {
        var councils = {},
            members = [];
        _.each(personData, function (data) {
            var person = new Person(data);
            person.positions.forEach(function (p) {
                if (!/Council/.test(p.office)) {
                    return;
                }
                if (p.start) {
                    if (!councils[p.start]) {
                        councils[p.start] = new Council();
                        councils[p.start].date = p.start;
                    }
                    councils[p.start].add.push(person);
                }
                else {
                    throw 'Missing start in ' + person.code;
                }
                if (p.end) {
                    if (!councils[p.end]) {
                        councils[p.end] = new Council();
                        councils[p.end].date = p.end;
{'fraction_non_alphanumeric': 0.13707995365005793, 'fraction_numerical': 0.005330243337195829, 'mean_word_length': 1.3201612903225806, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, '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': '285383', 'n_tokens_mistral': 2437, 'n_tokens_neox': 2254, 'n_words': 440}