Если нельзя, но очень хочется, то нужно обязательно и ничего в мире не стоит того, чтобы делать из этого проблему!


Интересна Java? Кликай по ссылке и регистрируйся!
Если тебе полезно что-то из того, чем я делюсь в своем блоге - можешь поделиться своими деньгами со мной.
с пожеланием
столько времени читатели провели на блоге - 
сейчас онлайн - 

пятница, 14 марта 2014 г.

Как сделать счетчик времени проведенного на блоге читателем

Гуглил я гуглил решение. Потом решил по старинке - взять и написать свое. Это не изобретать велосипед - не скажи. И это лучше чем готовый сервис, поскольку можно допиливать под свои нужды.

Итак проект maven, сервер на jetty/java, киент - java script/jquery, связь тудым-сюдым web socket.

Вот рабочий задеплоенный на сервак codenjoy.com код. Можно встраивать в свой блог. Только пока не гарантирую что при перезапуске не полетят все время (позже сделаю, чтобы оно сохранялось). Пока так - AS IS. Вот исходный код.
<script language="JavaScript" type="text/javascript" src="http://codenjoy.com/timer/timer.js"></script>
<script language="JavaScript" type="text/javascript" src="http://codenjoy.com/timer/jquery-1.11.0_min.js"></script>
<script language="JavaScript" type="text/javascript" >
    setupTimeWatcher("timer_info_div");
</script>
<center><div style="display:inline-flex;">
    <div id="timer_info_div"></div>
    <div> - столько времени читатели проводят на блоге</div>
</div></center>
Дальше код сервера
package com.apofig;

import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketServlet;
import org.json.JSONObject;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;

public class TimerServlet extends WebSocketServlet {

    public static HashMap<String, Integer> times = new HashMap<String, Integer<();

    @Override
    public void init() throws ServletException {
        super.init();
    }

    @Override
    public WebSocket doWebSocketConnect(HttpServletRequest httpRequest, String protocol) {

        return new WebSocket.OnTextMessage() {

            public Connection connection;

            @Override
            public void onMessage(String data) {
                try {
                    synchronized (times) {
                        JSONObject signal = new JSONObject(data);
                        String type = signal.getString("type");
                        String hash = signal.getString("hash");

                        if (!times.containsKey(hash)) {
                            times.put(hash, 0);
                        }

                        if (type.equals("tick")) {
                            int time = signal.getInt("time");
                            times.put(hash, times.get(hash) + time);
                        }

                        if (type.equals("get")) {
                            connection.sendMessage(String.valueOf(times.get(hash)));
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onOpen(WebSocket.Connection conn) {
                connection = conn;
            }

            @Override
            public void onClose(int closeCode, String message) {
                connection = null;
            }
        };
    }
}

И клиента
function setupTimeWatcher(timerDivId, reportToServerDelayInSec, getFromServerTotalTimeDelayInSec) {
    if (!reportToServerDelayInSec) reportToServerDelayInSec = 5;
    if (!getFromServerTotalTimeDelayInSec) getFromServerTotalTimeDelayInSec = 1;

    $().ready(function() {
        var total = 0;
        var activity = false;
        var hash = document.domain;

        var server = new WebSocket("ws://192.168.1.102:8080/timer/ws");
//        var server = new WebSocket("ws://tetrisj.jvmhost.net:12270/timer/ws");
        server.onopen = function() {
            server.onmessage = onGetTotal;
            tick(report, reportToServerDelayInSec * 1000);
            tick(getTotal, getFromServerTotalTimeDelayInSec * 1000);
        };

        // thanks to powtac (http://stackoverflow.com/questions/6312993/javascript-seconds-to-time-with-format-hhmmss)
        var toHHMMSS = function (seconds) {
            var sec_num = parseInt(seconds, 10); // don't forget the second param
            var hours   = Math.floor(sec_num / 3600);
            var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
            var seconds = sec_num - (hours * 3600) - (minutes * 60);

            if (hours   < 10) {hours   = "0"+hours;}
            if (minutes < 10) {minutes = "0"+minutes;}
            if (seconds < 10) {seconds = "0"+seconds;}
            var time    = hours+':'+minutes+':'+seconds;
            return time;
        }

        var onGetTotal = function (event) {
            var total = JSON.parse(event.data);
            $("#" + timerDivId).html(toHHMMSS(total));
        }

        var getTotal = function () {
            var request = { type : "get", hash : hash };
            server.send(JSON.stringify(request));
        }

        var onActivity = function() {
            activity = true;
        };

        var inc = function () {
            if (activity) total++;
            activity = false;
        };

        var tick = function(smth, delay) {
            setTimeout(function(){
                if (!!smth) {
                    smth();
                }
                tick(smth, delay);
            }, delay);
        };

        var report = function() {
            var data = { type : "tick", time : total, hash : hash };
            server.send(JSON.stringify(data));
            total = 0;
        };

        $(window).mousemove(onActivity);
        $(window).keypress(onActivity);
        $(window).scroll(onActivity);

        tick(inc, 1000);
    });
}

Собрать варник
mvn clean
mvn package
mvn war:war

Запустить джетти на локали
mvn jerry:run

Обратить внимание на урл сервера в клиенте

...
    $().ready(function() {
        var total = 0;
        var activity = false;
        var hash = document.domain;

        var server = new WebSocket("ws://192.168.1.102:8080/timer/ws"); // TODO вот тут айпишка и порт должны быть 
...

Так же внимательнее с контекстом "/timer/", если собрался поменять, то он встречается в pom.xml и timer.js

Время на разработку - 1 час 20 минут. Время на пост в блоге - 15 минут.

Комментариев нет:

Отправить комментарий