<commit_before>{% extends "basic.html" %}
{% load static %}

{% block content %}

<div id="canvas-container" class="white-background"">
    <p class="scoretitle">Attack visualisation</p>

        <canvas class="col-xs-12 white-background" id="c" >
        </canvas>
    </div>

    <script src="{% static "js/fabric.min.js" %}"></script>
    <script>
        (function() {
            var last_call_time = null;
            var garbage = [];
            function gc_round(canvas) {
                while(garbage.length > 0) {
                    canvas.remove(garbage.pop());
                }
            }

            init_image = function (data) {
                last_call_time = data['time'];

                data_users = data['gamers']['users_points'];

                var max_points = - Infinity;
                for (var i in data_users) {
                    p = Math.abs(data_users[i]['points']);
                    if (p > max_points)
                        max_points = p;
                }

                var canvas = this.__canvas = new fabric.StaticCanvas('c');

                canvas.setHeight(700);
                canvas.setWidth($('#canvas-container').width() );

                // compute max radius of a user circle
                var pi = 3.14;
                var minhw = Math.min(canvas.getWidth(), canvas.getHeight());
                var num_users = Object.keys(data_users).length;

                // radius of a big circle
                var max_circ_size = (pi * minhw) / (num_users * (1 + pi));
                var big_radius = minhw - 20;

                var user_circles = {};
                var i = 0;
                var min_circle_size = 20;

                for (k in data_users)
                {
                    angle = k * 2 * pi / num_users;
                    p = data_users[k]['points'];

                    var size = max_circ_size * 0.7 * Math.abs(p) / max_points + min_circle_size;

                    c = new fabric.Circle({
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - size,
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle) - size,
                            radius: size,
                            fill: p > 0 ? '#59ff59' : '#ff9191' });
                    user_circles[data_users[k]['username']] = c;


                    rect_h = 20;
                    rect_w = size * 2 + 5;
                    p = data_users[k]['attack_points'] + data_users[k]['victim_points'];
                    ratio = data_users[k]['attack_points'] / p;
                    r1 = new fabric.Rect({
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - rect_h / 2,
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle) - rect_w / 2,
                            width: rect_w * ratio,
                            height: rect_h,
                            fill: 'green' });

                    r2 = new fabric.Rect({
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - rect_h / 2,
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle) - rect_w / 2 + rect_w * ratio,
                            width: rect_w * (1 - ratio),
                            height: rect_h,
                            fill: 'red' });

                    score = new fabric.Text(data_users[k]['points'].toString(), {
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle),
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) + size + 15,
                            fill: 'black',
                            originX: "center",
                            originY: "center",
                            fontFamily: "Arial",
                            fontSize: 20
                    });

                    user = new fabric.Text(data_users[k]['username'].toString(), {
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle),
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - size - 15,
                            fill: 'black',
                            originX: "center",
                            originY: "center",
                            fontFamily: "Arial",
                            fontSize: 20
                    });

                    canvas.add(c, r1, r2, score, user);

                    i++;
                }

                function remove_element(elem, after) {
                    setTimeout(function() { elem.setOpacity(0); canvas.add(elem); garbage.push(elem); }, after + 70);
                }
                function animate_commet(N, base_size, dist, minx, miny, maxx, maxy, duration) {
                    animate_commet_particle(0, N, base_size, dist, minx, miny, maxx, maxy, duration);
                }

                function animate_commet_particle(n, N, base_size, dist, minx, miny, maxx, maxy, duration) {
                    if(n == N) {
                        return;
                    }
                    var rel = 1 - n / N;
                    var rect = new fabric.Circle({
                        top : 0,
                        left : 0,
                        radius : rel *  base_size,
                        fill : 'red',
                        opacity : rel,
                    });
                    animate(rect, minx, miny, maxx, maxy, duration);
                    setTimeout(function() { animate_commet_particle(n + 1, N, base_size, dist, minx, miny, maxx, maxy, duration); }, dist);
                }

                function animate(rect, minx, miny, maxx, maxy, duration) {
                    canvas.add(rect);
                    animate_one(rect, 'top', miny, maxy, duration);
                    animate_one(rect, 'left', minx, maxx, duration);
                    remove_element(rect, duration);
                }
                function animate_one(element, direction, min, max, duration) {
                    element.set(direction, min);
                    canvas.add(element);
                    element.animate(direction, max, {
                        duration: duration,
                        onChange: canvas.renderAll.bind(canvas),
                    });
                }


                // atack animations
                var attacks = data['attacks'];
                // console.log(attacks);
                for (var i in attacks)
                {
                    var attacker_c = user_circles[attacks[i]['attacker_username']];
                    var victim_c = user_circles[attacks[i]['victim_username']];
                    console.log(attacks[i]['attacker_username']);
                    var x0 = attacker_c.left + attacker_c.radius;
                    var y0 = attacker_c.top + attacker_c.radius;
                    var x1 = victim_c.left + victim_c.radius;
                    var y1 = victim_c.top + victim_c.radius;
                    var length = 500;

                    animate_commet(5, 5, 1, x0, y0, x1, y1, length);
                }

                // garbage collection
                gc_round(canvas);
            }

            var update_fun = function() {
                var last_call_str = null;
                if(last_call_time !== null) {
                  last_call_str = last_call_time;
                }

                $.ajax({
                        url: 'http://{{url}}/api',
                        type: 'GET',
                        data: {last_update: last_call_str},
                        success: function (data) { init_image(data) }
                });
                ast_call_time = new Date();
            }

            update_fun();
            setInterval(update_fun, 2000);
<commit_msg>bubble animation and comet colors<commit_after>{% extends "basic.html" %}
{% load static %}

{% block content %}

<div id="canvas-container" class="white-background"">
    <p class="scoretitle">Attack visualisation</p>

        <canvas class="col-xs-12 white-background" id="c" >
        </canvas>
    </div>

    <script src="{% static "js/fabric.min.js" %}"></script>
    <script>
        (function() {
            var last_call_time = null;
            var garbage = [];
            function gc_round(canvas) {
                while(garbage.length > 0) {
                    canvas.remove(garbage.pop());
                }
            }

            init_image = function (data) {
                last_call_time = data['time'];

                data_users = data['gamers']['users_points'];

                var max_points = - Infinity;
                for (var i in data_users) {
                    p = Math.abs(data_users[i]['points']);
                    if (p > max_points)
                        max_points = p;
                }

                var canvas = this.__canvas = new fabric.StaticCanvas('c');

                canvas.setHeight(700);
                canvas.setWidth($('#canvas-container').width() );

                // compute max radius of a user circle
                var pi = 3.14;
                var minhw = Math.min(canvas.getWidth(), canvas.getHeight());
                var num_users = Object.keys(data_users).length;

                // radius of a big circle
                var max_circ_size = (pi * minhw) / (num_users * (1 + pi));
                var big_radius = minhw - 20;

                var user_circles = {};
                var i = 0;
                var min_circle_size = 20;

                for (k in data_users)
                {
                    angle = k * 2 * pi / num_users;
                    p = data_users[k]['points'];

                    var size = max_circ_size * 0.7 * Math.abs(p) / max_points + min_circle_size;

                    c = new fabric.Circle({
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - size,
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle) - size,
                            radius: size,
                            fill: p > 0 ? '#59ff59' : '#ff9191' });
                    user_circles[data_users[k]['username']] = c;


                    rect_h = 20;
                    rect_w = size * 2 + 5;
                    p = data_users[k]['attack_points'] + data_users[k]['victim_points'];
                    ratio = data_users[k]['attack_points'] / p;
                    r1 = new fabric.Rect({
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - rect_h / 2,
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle) - rect_w / 2,
                            width: rect_w * ratio,
                            height: rect_h,
                            fill: 'green' });

                    r2 = new fabric.Rect({
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - rect_h / 2,
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle) - rect_w / 2 + rect_w * ratio,
                            width: rect_w * (1 - ratio),
                            height: rect_h,
                            fill: 'red' });

                    score = new fabric.Text(data_users[k]['points'].toString(), {
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle),
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) + size + 15,
                            fill: 'black',
                            originX: "center",
                            originY: "center",
                            fontFamily: "Arial",
                            fontSize: 20
                    });

                    user = new fabric.Text(data_users[k]['username'].toString(), {
                            left: canvas.getWidth() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.cos(angle),
                            top: canvas.getHeight() / 2 + (big_radius - 2 * max_circ_size) / 2 * Math.sin(angle) - size - 15,
                            fill: 'black',
                            originX: "center",
                            originY: "center",
                            fontFamily: "Arial",
                            fontSize: 20
                    });

                    canvas.add(c, r1, r2, score, user);

                    i++;
                }

                function remove_element(elem, after) {
                    setTimeout(function() {
                        elem.setOpacity(0);
                        canvas.add(elem);
                        garbage.push(elem);
                    }, after + 70);
                }
                function animate_comet(N, base_size, dist, minx, miny, maxx, maxy, color, duration) {
                    animate_comet_particle(0, N, base_size, dist, minx, miny, maxx, maxy, color, duration);
                }

                function animate_comet_particle(n, N, base_size, dist, minx, miny, maxx, maxy, color, duration) {
                    if(n == N) {
                        return;
                    }
                    var rel = 1 - n / N;
                    var rect = new fabric.Circle({
                        top : 0,
                        left : 0,
                        radius : rel *  base_size,
                        fill : color,
                        opacity : rel,
                    });

                    animate(rect, minx, miny, maxx, maxy, duration);
                    setTimeout(function() {
                        animate_comet_particle(n + 1, N, base_size, dist, minx, miny, maxx, maxy, color, duration);
                    }, dist);
                }

                function animate(rect, minx, miny, maxx, maxy, duration) {
                    canvas.add(rect);
                    animate_one(rect, 'top', miny, maxy, duration);
                    animate_one(rect, 'left', minx, maxx, duration);
                    remove_element(rect, duration);
                }
                function animate_one(element, direction, min, max, duration) {
                    element.set(direction, min);
                    canvas.add(element);
                    element.animate(direction, max, {
                        duration: duration,
                        onChange: canvas.renderAll.bind(canvas),
                    });
                }
                function animate_bubble(x, y, minr, maxr, color, length) {
                    var circ = new fabric.Circle({
                      top : y - minr,
                      left : x - minr,
                      radius : minr,
                      fill: "rgba(0, 0, 0, 0)",
                      stroke: color,
                      strokeWidth: 4,
                    });
                    canvas.add(circ);

                    animate_one(circ, 'radius', minr, maxr, length);
                    animate_one(circ, 'top', y - minr, y - maxr, length);
                    animate_one(circ, 'left', x - minr, x - maxr, length);
                    animate_one(circ, 'opacity', 1, 0, length);

                    remove_element(circ, length);
                }

                function get_attack_color(attack) {
                    var table = {
                        "null": "black",
                        "pdf": "red",
                        "xls": "green",
                        "exe": "brown",
                        "web": "blue"
                    };

                    return table[attack['type']];
                }

                // atack animations
                var attacks = data['attacks'];
                for (var i in attacks)
                {
                    var attacker_c = user_circles[attacks[i]['attacker_username']];
                    var victim_c = user_circles[attacks[i]['victim_username']];
                    console.log(attacks[i]['attacker_username']);
                    var x0 = attacker_c.left + attacker_c.radius;
                    var y0 = attacker_c.top + attacker_c.radius;
                    var x1 = victim_c.left + victim_c.radius;
                    var y1 = victim_c.top + victim_c.radius;

                    var radius = attacker_c.radius;
                    var length = 500; // TODO: constant speed not constant time

                    animate_comet(5, 5, 1, x0, y0, x1, y1, get_attack_color(attacks[i]), length);
                    animate_bubble(x0, y0, radius, radius + 20, attacker_c.getFill(), length);
                }

                // garbage collection
                gc_round(canvas);
            }

            var update_fun = function() {
                var last_call_str = null;
                if(last_call_time !== null) {
                  last_call_str = last_call_time;
                }

                $.ajax({
                        url: 'http://{{url}}/api',
                        type: 'GET',
                        data: {last_update: last_call_str},
                        success: function (data) { init_image(data) }
                });
                ast_call_time = new Date();
            }

            update_fun();
            setInterval(update_fun, 2000);

{'fraction_non_alphanumeric': 0.11294781382228491, 'fraction_numerical': 0.01235543018335684, 'mean_word_length': 1.0883600377002827, 'pattern_counts': {'":': 5, '<': 21, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4901130', 'n_tokens_mistral': 5079, 'n_tokens_neox': 4522, 'n_words': 1067}