text:
"use strict";

var opt  = require('../options.js');
var utils = require('util');
var events = require('events');
var fs = require('fs');
var crpt = require('crypto');
var markup = require('./wakabamark.js');
var msgcrypt = require('../msgcrpyt.js');
var bs58 = require('bs58');
var ntp_time = require('../ntp_time.js');

var EC = require('elliptic').ec;
var ec = new EC('secp256k1');

var _spoilerTag  = "%" + "%";

var $ = null, quotedText = '';

var dateToStr = function(date, onlyNums) {
    var dateo = new Date();
    dateo.setTime(date * 1000);

    var z = function(i) {
        if (parseInt(i) < 10) return "0" + i;
        return i;
    };

    if(onlyNums){
        return '' + dateo.getFullYear() + z(dateo.getMonth() + 1) + z(dateo.getDate())+ '_' + z(dateo.getHours()) + z(dateo.getMinutes());
    }
    return '' + dateo.getFullYear() + '-' + z(dateo.getMonth() + 1) + '-' + z(dateo.getDate()) + ' ' + z(dateo.getHours()) + ':' + z(dateo.getMinutes());
};

var Ui = function Ui(app){
	events.EventEmitter.call(this);
	this.app = app;
	$ = app.$;
	this.state = 'messages';
	this.showSub = null;
	this.showThread = null;
	this.showPage = 0;
};
utils.inherits(Ui, events.EventEmitter);

Ui.prototype.inject = function inject(){
	var self = this;

	$('#show_contacts').on('click', function(){
		$('nav>ul li').removeClass('active');
		$('#page-wrapper .page').removeClass('show');
		$('#show_contacts').parent().addClass('active');
		$('#page-wrapper #contacts').addClass('show');
		this.state = 'contacts';
	}.bind(this));

	$('#show_subs').on('click', function(){
		$('nav>ul li').removeClass('active');
		$('#page-wrapper .page').removeClass('show');
		$('#show_subs').parent().addClass('active');
		$('#page-wrapper #subs').addClass('show');
		this.renderSubs();
		this.state = 'subs';
	}.bind(this));

	$('#show_messages').on('click', function(){
		$('nav>ul li').removeClass('active');
		$('#page-wrapper .page').removeClass('show');
		$('#show_messages').parent().addClass('active');
		$('#page-wrapper #messages').addClass('show');
		this.state = 'messages';
	}.bind(this));

	$('#add_sub_key').on('click', function(){
		this.app.keys.addSub($('#sub_address').val());
		this.renderSubs();
		$('#sub_address').val('');
	}.bind(this));

	this.renderSubs();
	$('#load_spalsh').addClass('hidden');
	$('#wrapper').removeClass('hidden');
	$('#page_refresh').on('click', function(){
		this.renderPage();
	}.bind(this));

	$('#brand-version').html('BaraBaraDark v'+opt.pkg.version);

	$('#saveFileDialog').on('change', function(e){
		if(e.target.files.length === 0) return false;

		fs.readFile(opt.datadir + '/files/' + e.target.dataset.id, function (err, data) {
		  if (err) throw err;
		  fs.writeFile(e.target.files[0].path, data, function (err) {
			  if (err) throw err;
			  console.log('saved ' + e.target.dataset.id + ' to ' + e.target.files[0].path);
			  e.target.value = null;
			});
		});
    });
};

Ui.prototype.renderSubs = function renderSubs() {

    var code = '
', cnt = 1, mnu = '';

    for (var c in this.app.keys.subs) {

        code += '
' +
            '
' + c + '
' +
            '
' + this.app.keys.subs[c].name + '   [delete] ' +
            '

#'+(cnt++)+'

';
        mnu += '
' + this.app.keys.subs[c].name + '
';
    }

    var cont_list = $(code);
    var mnu_list = $(mnu);
    cont_list.find('.cont_identi').identicon5({
        rotate: true,
        size: 48
    });

    cont_list.find('a.hidbord_subs_action').on('click', this.deleteSub.bind(this));

    $('#subs_list').empty().append(cont_list);
    $('.side-nav ul').empty().append(mnu_list);

    $('.side-nav ul').find('a.board_nav_link').on('click', this.navToBoard.bind(this));
};

Ui.prototype.deleteSub = function deleteSub(e) {
    var action = $(e.target).text(),
        key = $(e.target).attr('alt');

    if (action == 'delete' && window.confirm('Really delete "' +  this.app.keys.subs[key].name + '" subscription?')) {
        this.app.keys.deleteSub(key);
        this.renderSubs();
    }
};

Ui.prototype.navToBoard = function navToBoard(e) {
    var key = $(e.target).attr('alt');
    this.showSub = key;
	this.showThread = 0;
	this.replyTo = 0;
	this.showPage = 0;
	this.posts = {};
	this.postsIds = [];

	$('.side-nav ul li').removeClass('active');
	$('.side-nav ul li a[alt='+key+']').parent().addClass('active');

	this.renderPage();
};

Ui.prototype.renderPage = function renderPage() {
	$('#messages').empty().append('

' + this.showSub + '
 ' +
		this.app.keys.subs[this.showSub].name + '
'+

		'

'+
            	'
'+
            	(this.showThread === 0 ? 'Create new Thread': 'Reply to #'+this.showThread.substr(0, 8))+
            	'
'+
            	'
'+
            	'
'+
				'<form id="postform">'+

	            '
' +
	            '              <button type="button" class="btn btn-default" title="Bold"    id="hidbordBtBold"    data-mode="B">B</button>' +
				'              <button type="button" class="btn btn-default" title="Italic"  id="hidbordBtItalic"  data-mode="i">i</button>' +
				'              <button type="button" class="btn btn-default" title="Strike"  id="hidbordBtStrike"  data-mode="S">S</button>' +
				'              <button type="button" class="btn btn-default" title="Spoiler" id="hidbordBtSpoiler" data-mode="%">%</button>' +
				'              <button type="button" class="btn btn-default" title="Code"    id="hidbordBtCode"    data-mode="C">js</button>' +
				'              <button type="button" class="btn btn-default" title="Irony"   id="hidbordBtIrony"   data-mode=":)">:)</button>' +
				'              <button type="button" class="btn btn-default" title="Spoiler" id="hidbordBtQuote"   data-mode="q">></button>' +
	            '
'+
				'        <input type="file" id="c_file" name="c_file" style="max-width: 300px;" data-id="file_selector">' +

				'<textarea id="reply_text" rows="6" cols="70"></textarea>

'+
				'<input type="button" value="Post" id="post_edit_send">'+

				' edit | preview
'+
				'</form>'+

            	'
'+
            	'
'+
            	'

'+

				'
[' + (this.showThread === 0 ? 'Create new Thread' : 'Post reply') + ']
'+
				'
 Loading...

' +
				(this.showThread === 0 ? '': '
[Post reply]
')

	).find('.cont_identi').identicon5({
        rotate: true,
        size: 48
    });

    $('#hidbordBtQuote').on('mouseover', function(e) {
        quotedText = markup.quoteSelection();
    });

    $('#hidbordTextControls button').on('click', function(e) {
        var mode = this.dataset.mode,
            ta = $('textarea#reply_text'),
            taStart = ta[0].selectionStart,
            taEnd = ta[0].selectionEnd,
            taPost = ta.val().length - taEnd, tag, selected, parts;

        if (mode == 'q') {
            if (taStart !== taEnd && quotedText.length === 0) {
                quotedText = ta.val().substring(taStart, taEnd);
            }
            if (quotedText.length > 0) {
                //quotedText = '> ' + quotedText.replace(/\n/gm, "\n> ") + "\n";
                ta.val(ta.val().substring(0, taStart) + quotedText + ta.val().substring(taEnd));
            }
        }

        if (mode == 'B' || mode == 'i' || mode == 'S' || mode == ':)') {
            tag = mode == 'B' ? '**' : '*';
            tag = mode == 'S' ? '--' : tag;
            tag = mode == ':)' ? '++' : tag;
             selected = ta.val().substring(taStart, taEnd).split("\n");
            for (var i = 0; i < selected.length; i++) {
                parts = selected[i].match(/^(\s*)(.*?)(\s*)$/);
                selected[i] = parts[1] + tag + parts[2] + tag + parts[3];
            }
            ta.val(ta.val().substring(0, taStart) + selected.join("\n") + ta.val().substring(taEnd));
        }

        if (mode == '%' || mode == 'C') {
            tag = mode == '%' ? _spoilerTag : '`';
            var tagmultiline = mode == '%' ? _spoilerTag : '``';
            selected = ta.val().substring(taStart, taEnd).split("\n");

            if (selected.length > 1) {
                selected = "\n" + tagmultiline + "\n" + selected.join("\n") + "\n" + tagmultiline + "\n";
            } else {
                parts = selected[0].match(/^(\s*)(.*?)(\s*)$/);
                selected = parts[1] + tag + parts[2] + tag + parts[3];
            }
            ta.val(ta.val().substring(0, taStart) + selected + ta.val().substring(taEnd));
        }

		ta.focus();
        ta[0].selectionStart = ta.val().length - taPost;
        ta[0].selectionEnd = ta.val().length - taPost;

    });

	$('#reply_form #c_file').on('change', handleFileSelect)
		.on('mouseover', do_imgpreview_popup)
        .on('mouseout', del_popup)
        .on('click', function() {
           $('#hidbord_popup').remove();
        });

    $('#reply_form #post_preview_link').on('click', function(){
    	$('#reply_form #post_preview').show();
    	$('#reply_form #reply_text').hide();
    	$('#reply_form #post_preview').empty().append(markup.wkbmrk($('#reply_form #reply_text').val()).msg).show();
    });

    $('#reply_form #post_edit_link').on('click', function(){
    	$('#reply_form #post_preview').hide();
    	$('#reply_form #reply_text').show();
    });

    if(this.showThread == '0'){
    	this.app.db.getBoardPages(this.showSub)
    	.then(function(val){
	    		if(val.board == this.showSub && this.showThread == '0')
	    			this.makePagination(val.threads);
	    	}.bind(this),
	    	function(err){
	    		throw err;
	    	});
    }

    $('#reply_form #post_edit_send').on('click', function(){
    	var message = {
    		text: ''+$('#reply_form #reply_text').val(),
    		timestamp: Math.floor(ntp_time.now() / 1000),
    		parent: this.replyTo
    	}, fileData = null;

    	if (selectedFile.path){
			fileData = fs.readFileSync(selectedFile.path);
			message.filename = selectedFile.name;
			message.fileIsImage = selectedFile.isImage;
    	}

    	var packed = msgcrypt.encodeMessage(message, fileData, [this.showSub], null);
    	if(packed.length > 2*1024*1024 - 15){
    		window.alert('Message is to large! Size must be less than 2MB.');
			return false;
    	}

    	var hash = crpt.createHash('sha256').update(packed).digest();

    	fs.writeFile(opt.datadir + '/temp_msg/' + hash.toString('hex'), packed);
    	if(fileData){
    		fs.writeFileSync(opt.datadir + '/files/' + hash.toString('hex'), fileData);
    	}

		this.app.db.bumpThread(message.parent, message.timestamp);

		var postData = {
      		"id": hash.toString('hex'),
      		"parent":  message.parent,
      		"posted_at": message.timestamp,
      		"bumped":  message.timestamp,
      		"message": message.text,
      		"sent_to": this.showSub,
      		"state": 'sending',
      		"file": '',
      		"file_size": 0,
      		"file_ext": 'none'
      	};

      	if(fileData){
    		postData.file = selectedFile.name;
    		postData.file_size = selectedFile.size;
    		postData.file_ext = selectedFile.isImage ? 'image' : 'file';
    	}

		this.app.db.addPost(postData, function(){
      		if(this.showThread === 0){
      			this.showPage = 0;
				this.posts = [];

				this.renderPage();
			}else{
				this.postReceived(hash.toString('hex'));
			}
      	}.bind(this));

      	this.app.ds.insertFile(packed);
      	selectedFile = {};
      	$('#reply_form #reply_text').val('');
      	$('#post_edit_link').click();
      	$('#reply_form').hide();
      	//$('h1').after($('#reply_form').detach());

    }.bind(this));

    this.posts = {};
	this.postsIds = [];
	this.postsRefs = {};

    if(this.showThread !== 0){
	    this.app.db.getBoardThreads(this.showSub, this.showThread, this.showPage, function(rows, board){
			if(board != this.showSub){
				return false;
			}
			$('#thread_render').empty().append('
');

			if(this.showThread !== 0 && rows.length === 0){
				this.showThread = 0;
				this.showPage = 0;
				this.renderPage();
				return false;
			}

			for (var i = 0; i < rows.length; i++) {
				$('#thread_render').append(this.renderMsg(rows[i]));
				this.postsIds.push(rows[i].id);
				this.posts[rows[i].id] = rows[i];
			}

			this.renderRefs($('#thread_render'), this.postsRefs);
			this.bindEvents('#thread_render');
		}.bind(this));
	}else{
		this.app.db.getPage(this.showSub, this.showPage, 10, 3)
		    .then(function(val){
		    	var i, j;

		    	$('#thread_render').empty();

		      	for (i = 0; i < val.length; i++) {

		      		$('#thread_render').append('
' + this.renderMsg(val[i]));
		      		this.postsIds.push(val[i].id);
					this.posts[val[i].id] = val[i];

		      		if(val[i].post_count > 3){
		      			$('#thread_render').append('' + (val[i].post_count - 3) +
		      				' posts omitted.  [Reply]');
		      		}else{
		      			$('#thread_render').append('[Reply]');
		      		}

		      		for (j = 0; j < val[i].replies.length; j++) {
		      			$('#thread_render').append(this.renderMsg(val[i].replies[j]));
		      			this.postsIds.push(val[i].replies[j].id);
						this.posts[val[i].replies[j].id] = val[i].replies[j];
		      		}
		      	}
		      	this.renderRefs($('#thread_render'), this.postsRefs);
		      	this.bindEvents('#thread_render');
		    }.bind(this), function(val){throw val;});
	}
};

Ui.prototype.renderMsg = function renderMsg(data) {
    var m = markup.wkbmrk(data.message),
    	fileblock = '';

    if(data.file_ext == 'image'){
		fileblock = '
'+markup.safe_tags(data.file)+' ' + bytesMagnitude(data.file_size) + '
' +
		  '';
    }

	if(data.file_ext == 'file'){
		fileblock = '
'+markup.safe_tags(data.file)+' ' + bytesMagnitude(data.file_size) + '
';
    }

    var html = //(data.parent == '0' ? '
': '
')+
    	'

'+
    	'
'+
    	'         '+
    	'Anonymous'+
    	' (' + dateToStr(data.posted_at) + ') #'+data.id.substr(0, 8)+''+
    	(data.state == 'sending' ? ' (message is in send queue)': '') +
		(data.state == 'placeholder' ? ' (message is not recived. This is Placeholder)': '') +
    	'
'+
    	'
'+
    	'
'+
    	fileblock+m.msg +
    	'

'+
    	'
'+
    	'
'+
    	'

';

	for (var j = 0; j < m.refs.length; j++) {
    	this.postsRefs[m.refs[j]] = this.postsRefs[m.refs[j]] || {};
    	this.postsRefs[m.refs[j]][data.id] = data.id;
    }

    return html;
};

Ui.prototype.renderRefs = function renderRefs(el, data) {
	var r, l;

	for(r in data){
		el.find('#msg_' + r + ' #reply_links').empty();
		for(l in data[r]){
			el.find('#msg_' + r + ' #reply_links').append('>>' + l.substr(0, 8) + '');
		}
	}

    return true;
};

Ui.prototype.makePagination = function makePagination(numThreads) {
    var numPages = Math.ceil(numThreads / 10),
    	code = '
', i;

	for (i = 0; i < numPages; i++) {
		code += '
' + i +'
';
	}

	code += '
';

    $('#board_pagination').empty().append(code);

    $('#board_pagination a').on('click', function(e){
    	var key = parseInt($(e.target).text());
				this.showPage = key;
				this.posts = [];
				this.renderPage();
    }.bind(this));
};

Ui.prototype.bindEvents = function bindEvents(selector) {
	var s = $(selector);

	s.find('.panel-body').on('mouseout', function() {
        $(this).removeClass('hidbord_msg_new');
    });

	s.find('a.thread_reply').on('click', function(e){
		e.preventDefault();
		e.stopPropagation();
		this.showThread = e.target.dataset.id;
		this.showPage = 0;
		this.posts = [];
		this.renderPage();
	}.bind(this));

	s.find('a.hidbord_msglink').on('mouseover', function(e){
        var msgid = e.target.dataset.id;
        msgPopupTimers[msgid] = setTimeout(function() {
            do_popup(e, this);
        }.bind(this), 200);

    }.bind(this)).on('mouseout', del_popup);

	s.find('img.img_thumb_size').on('click', function(e){
        $(e.target).toggleClass('img_thumb_size');
    });

	s.find('a.post_file_link').on('click', function(e){
		e.preventDefault();
		e.stopPropagation();
		console.dir({name: e.target.dataset.name, id: e.target.dataset.id});
		$('#saveFileDialog').attr('nwsaveas', e.target.dataset.name);
		$('#saveFileDialog').attr('data-id', e.target.dataset.id);
        setTimeout(function(){$('#saveFileDialog').click();}, 150);
    });

	s.find('span.hidbord_mnu_reply').on('click', function(e){
		e.preventDefault();
		e.stopPropagation();
		var id = e.target.dataset.id;
		this.replyTo = e.target.dataset.parent;
		$('#msg_' + id).parent().after($('#reply_form').detach());

		$('#reply_form div.panel-heading').html('Reply to #'+this.replyTo.substr(0, 8));

		$('#reply_form').show();
		$('#post_edit_link').click();
		var ta = $('#reply_form textarea');
		insertInto(ta[0], '>>'+id+'\n');
		ta.focus();

	}.bind(this))
		.on('mouseover', function(e) {
            quotedText = markup.quoteSelection();
        });

    $('a.do_reply').on('click', function(e){
		e.preventDefault();
		e.stopPropagation();

		this.replyTo = e.target.dataset.parent;
		$(e.target).parent().after($('#reply_form').detach());
		$('#reply_form').show();

		$('#reply_form div.panel-heading').html((this.replyTo == '0' ? 'Create new Thread': 'Reply to #'+this.replyTo.substr(0, 8)));

		$('#post_edit_link').click();

		$('#reply_form textarea').focus();

	}.bind(this))
		.on('mouseover', function(e) {
            quotedText = markup.quoteSelection();
        });
};

var msgPopupTimers = {}, popup_del_timer;

function del_popup(e) {
    var msgid = e.target.dataset.id;
    clearTimeout(msgPopupTimers[msgid]);

    if(msgid == 'file_selector'){
        $('#file_selector').remove();
        return;
    }

    msgPopupTimers[msgid] = setTimeout(function() {
        if(msgid == 'msg_preview'){
            $('#prev_popup').remove();
        }else{
            $('#hidbord_popup_' + msgid).remove();
        }
    }, 200);
}

var do_popup = function(e, ui) {
	var msgid = e.target.dataset.id,
		bbox  = e.target.getBoundingClientRect(),
		css = {position: "fixed", 'z-index': 200, left: bbox.left + 'px'},
		wh = $(window).height(),
		ww = $(window).width();

	if(bbox.top > wh / 2){
		css.bottom = (wh - bbox.top) + 'px';
	}else{
		css.top = bbox.bottom + 'px';
	}

	$('body').append('

');
	if(msgid in ui.posts){
		$('#hidbord_popup_'+ msgid).css(css).append(ui.renderMsg(ui.posts[msgid]));
		$('#hidbord_popup_'+ msgid + ' .panel').css({margin: 0, 'box-shadow': '0 1px 10px rgba(0, 0, 0, 0.3)'});
		ui.renderRefs($('#hidbord_popup_' + msgid), ui.postsRefs);
    	ui.bindEvents('#hidbord_popup_' + msgid);
	}else{
		ui.app.db.getPost(msgid).then(function(data){
			$('#hidbord_popup_'+ msgid).css(css).append(this.renderMsg(data));
			$('#hidbord_popup_'+ msgid + ' .panel').css({margin: 0, 'box-shadow': '0 1px 10px rgba(0, 0, 0, 0.3)'});
			this.renderRefs($('#hidbord_popup_' + msgid), ui.postsRefs);
    		this.bindEvents('#hidbord_popup_' + msgid);
		}.bind(ui),function(err){
			$('#hidbord_popup_'+ msgid).css(css).append('
NOT FOUND
');
		}.bind(ui));
	}

	var local_popup_del_timer;

    $('#hidbord_popup_' + msgid).on('mouseover', function() {
        clearTimeout(local_popup_del_timer);
        clearTimeout(msgPopupTimers[msgid]);
    }).on('mouseout', function(){
        local_popup_del_timer = setTimeout(function() {
            $('#hidbord_popup_' + msgid).remove();
        }, 200);
    });

};

var bytesMagnitude = function(bytes){
    if(bytes < 1024){
        return bytes + ' B';
    }else if (bytes < 1024 * 1024){
        return (bytes / 1024).toFixed(2) + ' KB';
    }else{
        return (bytes / 1024 / 1024).toFixed(2) + ' MB';
    }
};

var do_imgpreview_popup = function(e) {
    $('#file_selector').remove();
    if (!selectedFile.path) return;

    var txt = '

'+
              (selectedFile.isImage ? '
': '')+
               markup.safe_tags(selectedFile.name) + '
'+bytesMagnitude(selectedFile.size)+'
'+
              '
',
        bbox  = e.target.getBoundingClientRect(),
		css = {position: "fixed", 'z-index': 200, left: bbox.left + 'px'},
		wh = $(window).height(),
		ww = $(window).width();

	if(bbox.top > wh / 2){
		css.bottom = (wh - bbox.top + 5) + 'px';
	}else{
		css.top = (bbox.bottom + 5) + 'px';
	}

    $('body').append('

 0 && quotedText != '> \n'){
        text += quotedText;
    }

    var start = textarea.selectionStart;
    var end = textarea.selectionEnd;
    textarea.value = textarea.value.substr(0, start) + text + textarea.value.substr(end);
    textarea.setSelectionRange(start + text.length, start + text.length);
};

var selectedFile = {};

function handleFileSelect(evt) {

	if(evt.target.files.length === 0){
		evt.target.value = null;
		selectedFile = {};
		return false;
	}

    var files = evt.target.files[0]; // FileList object
    if(files.size > 2096128){
		selectedFile = {};
		evt.target.value = null;
		window.alert('File is to large! Size must be less than 2MB.');
		return false;
    }

    selectedFile.name = files.name;
    selectedFile.size = files.size;
    selectedFile.path = files.path;
    selectedFile.isImage = !!files.name.match(/(gif|png|jpe?g)$/i);
    console.dir(files);

}

Ui.prototype.postReceived = function postReceived(id) {

	this.app.db.getPost(id).then(function(data){

		if(!data) return false;

/*		var notification = new window.Notification("New post",{body: data.message});

		notification.onshow = function () {
		  setTimeout(function() {notification.close();}, 15000);
		};*/

		if(data.parent != this.showThread || this.showThread === 0) return true;

		if(data.id in this.posts){
			$('#thread_render #msg_'+data.id).parent().replaceWith(this.renderMsg(data));
			$('#thread_render #msg_'+ data.id + ' .panel-body').addClass('hidbord_msg_new');
			this.posts[data.id] = data;
			this.renderRefs($('#thread_render #msg_'+ data.id), this.postsRefs);
			this.bindEvents('#thread_render #msg_' + data.id);
			return true;
		}

		if(this.posts[this.postsIds[this.postsIds.length - 1]].posted_at < data.posted_at){
			$('#thread_render').append(this.renderMsg(data));
			$('#thread_render #msg_'+ data.id + ' .panel-body').addClass('hidbord_msg_new');
			this.postsIds.push(data.id);
			this.posts[data.id] = data;
			this.renderRefs($('#thread_render #msg_'+ data.id), this.postsRefs);
			this.bindEvents('#thread_render #msg_' + data.id);
			return true;
		}

		var i;
		for (i = 0; i < this.postsIds.length; i++) {
			if(this.posts[this.postsIds[i]].posted_at > data.posted_at) break;
		}

		$('#thread_render #msg_'+this.postsIds[i]).before(this.renderMsg(data));
		$('#thread_render #msg_'+ data.id + ' .panel-body').addClass('hidbord_msg_new');

		this.posts[data.id] = data;
		this.postsIds.splice(i, 0, data.id);

		this.renderRefs($('#thread_render #msg_'+ data.id), this.postsRefs);
		this.bindEvents('#thread_render #msg_' + data.id);

	}.bind(this),function(err){
		console.error(err);
	}.bind(this));

};

module.exports = Ui;


text:
package com.xt.service.stat.impl;

import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xt.bean.XtParmas;
import com.xt.dao.stat.IMyStatMapper;
import com.xt.service.stat.IMyStatMapperService;
/**
 *
 * 统计信息的处理
 * MyStatMapperService
 * 创建人:肖腾
 * 时间:2016年1月15日-上午6:55:05
 * @version 1.0.0
 *
 */
@Service
public class MyStatMapperService implements IMyStatMapperService {

	@Autowired
	private IMyStatMapper myStatMapper;

	/**
	 *
	 * (按照年份统计后台日志的系信息)
	 * com.xt.service.stat
	 * 方法名:groupState
	 * 创建人:肖腾
	 * 时间:2016年1月15日-上午6:53:06
	 * @param parmas
	 * @return List<HashMap<String,Object>>
	 * @exception
	 * @since  1.0.0
	 */
	@Override
	public List<HashMap<String, Object>> groupState(XtParmas parmas) {
		return myStatMapper.groupState(parmas);
	}

	@Override
	public List<HashMap<String, Object>> groupStatByMonth(XtParmas parmas) {
		return  myStatMapper.groupStatByMonth(parmas);
	}

	@Override
	public int groupStatByMonthCount(XtParmas parmas) {
		return myStatMapper.groupStatByMonthCount(parmas);
	}

}

redpajama_set_name: RedPajamaGithub


text:
package divconq.filestore;

import divconq.lang.op.FuncCallback;
import divconq.script.StackEntry;
import divconq.xml.XElement;

public interface IFileCollection {
	CommonPath path();
	void next(FuncCallback<IFileStoreFile> callback);
	void forEach(FuncCallback<IFileStoreFile> callback);

	// scripts
	public void operation(final StackEntry stack, XElement code);
}


text:
template<typename T>
class List {
public:
  virtual ~List() = default;

  virtual T& value_at(std::size_t i) = 0;
  virtual const T& value_at(std::size_t i) const = 0;
  virtual T& front() = 0;
  virtual T& back() = 0;
  virtual const T& front() const = 0;
  virtual const T& back() const = 0;

  virtual bool empty() const = 0;
  virtual std::size_t size() const = 0;

  virtual void insert_at(std::size_t i, const T& v) = 0;
  virtual void insert_at(std::size_t i, T&& v) = 0;
  virtual void push_front(const T& v) = 0;
  virtual void push_front(T&& v) = 0;
  virtual void push_back(const T& v) = 0;
  virtual void push_back(T&& v) = 0;

  virtual T remove_at(std::size_t i) = 0;
  virtual T pop_front() = 0;
  virtual T pop_back() = 0;

  virtual void clear() = 0;
  virtual std::list<T> to_std_list() const = 0;
};

// Singly-linked List implementation (without sentinels)
template<typename T>
class SinglyLinkedList : public List<T> {
public:
  SinglyLinkedList(); // O(1)
  SinglyLinkedList(const SinglyLinkedList& o); // O(n)
  SinglyLinkedList(SinglyLinkedList&& o); // O(1)
  ~SinglyLinkedList(); // O(n)

  T& value_at(std::size_t i); // O(i)
  const T& value_at(std::size_t i) const; // O(i)
  T& front(); // O(1)
  T& back(); // O(n)
  const T& front() const; // O(1)
  const T& back() const; // O(n)

  bool empty() const; // O(1)
  std::size_t size() const; // O(1)

  void insert_at(std::size_t i, const T& v); // O(i)
  void insert_at(std::size_t i, T&& v); // O(i)
  void push_front(const T& v); // O(1)
  void push_front(T&& v); // O(1)
  void push_back(const T& v); // O(n)
  void push_back(T&& v); // O(n)

  T remove_at(std::size_t i); // O(i)
  T pop_front(); // O(1)
  T pop_back(); // O(n)

  void clear(); // O(n)
  std::list<T> to_std_list() const; // O(n)

private:
  struct Node {
    Node(const T& v, Node* n = nullptr);
    Node(T&& prv, Node* n = nullptr);
    T data;
    Node* next;
  };

  Node* _head;
  std::size_t _size;

  Node* get_node_at(std::size_t i) const;
};

template<typename T>
SinglyLinkedList<T>::Node::Node(const T& v, Node* n) : data(v), next(n) {
}

template<typename T>
SinglyLinkedList<T>::Node::Node(T&& prv, Node* n) : data(std::move(prv)), next(n) {
}

template<typename T>
SinglyLinkedList<T>::SinglyLinkedList() : _head(nullptr), _size(0) {
}

template<typename T>
SinglyLinkedList<T>::SinglyLinkedList(const SinglyLinkedList& o) : _head(nullptr), _size(0) {
  Node* oit = o._head;
  Node** current = &_head;
  while(oit != nullptr) {
    *current = new Node(oit->data);
    _size++;
    // next pointer of current will be updated in the following cycle
    current = &((*current)->next);
    oit = oit->next;
  }
}

template<typename T>
SinglyLinkedList<T>::SinglyLinkedList(SinglyLinkedList&& o) : _head(o._head), _size(o._size) {
  o._head = nullptr;
  o._size = 0;
}

template<typename T>
bool SinglyLinkedList<T>::empty() const {
  return _head == nullptr;
}

template<typename T>
std::size_t SinglyLinkedList<T>::size() const {
  return _size;
}

template<typename T>
SinglyLinkedList<T>::~SinglyLinkedList() {
  clear();
}

template<typename T>
T& SinglyLinkedList<T>::value_at(std::size_t i) {
  assert(i >= 0 && i < size());
  return get_node_at(i)->data;
}

template<typename T>
const T& SinglyLinkedList<T>::value_at(std::size_t i) const {
  assert(i >= 0 && i < size());
  return get_node_at(i)->data;
}

template<typename T>
T& SinglyLinkedList<T>::front() {
  return value_at(0);
}

template<typename T>
T& SinglyLinkedList<T>::back() {
  return value_at(size() - 1);
}

template<typename T>
const T& SinglyLinkedList<T>::front() const {
  return value_at(0);
}

template<typename T>
const T& SinglyLinkedList<T>::back() const {
  return value_at(size() - 1);
}

template<typename T>
typename SinglyLinkedList<T>::Node*
SinglyLinkedList<T>::get_node_at(std::size_t i) const {
  assert(i >= 0 && i < size());
  Node* current = _head;
  while(i > 0) {
    current = current->next;
    i--;
  }
  return current;
}

template<typename T>
void SinglyLinkedList<T>::clear() {
  while(!empty()) {
    pop_front();
  }
}

template<typename T>
void SinglyLinkedList<T>::insert_at(std::size_t i, const T& v) {
  assert(i >= 0 && i <= size());
  if(i == 0) {
    _head = new Node(v, _head);
  } else {
    // from the assert and first condition we know that here size() > 0
    Node* before_at = get_node_at(i - 1);
    before_at->next = new Node(v, before_at->next);
  }
  _size++;
}

// find out how to de-duplicate code regarding lvalues and rvalue references
template<typename T>
void SinglyLinkedList<T>::insert_at(std::size_t i, T&& v) {
  assert(i >= 0 && i <= size());
  if(i == 0) {
    _head = new Node(v, _head);
  } else {
    // from the assert and first condition we know that here size() > 0
    Node* before_at = get_node_at(i - 1);
    before_at->next = new Node(std::move(v), before_at->next);
  }
  _size++;
}

template<typename T>
T SinglyLinkedList<T>::remove_at(std::size_t i) {
  assert(i >= 0 && i < size());
  if(i == 0) {
    Node* old_head = _head;
    T ret = std::move(old_head->data);
    _head = _head->next;
    delete old_head;
    _size--;
    return ret;
  } else {
    // there are at least 2 nodes
    Node* before_last = get_node_at(size() - 2);
    T ret = std::move(before_last->next->data);
    delete before_last->next;
    before_last->next = nullptr;
    _size--;
    return ret;
  }
}

template<typename T>
void SinglyLinkedList<T>::push_back(const T& v) {
  return insert_at(size(), v);
}

template<typename T>
void SinglyLinkedList<T>::push_back(T&& v) {
  return insert_at(size(), v);
}

template<typename T>
void SinglyLinkedList<T>::push_front(const T& v) {
  return insert_at(0, v);
}

template<typename T>
void SinglyLinkedList<T>::push_front(T&& v) {
  return insert_at(0, v);
}

template<typename T>
T SinglyLinkedList<T>::pop_front() {
  return remove_at(0);
}

template<typename T>
T SinglyLinkedList<T>::pop_back() {
  return remove_at(size() - 1);
}

template<typename T>
std::list<T> SinglyLinkedList<T>::to_std_list() const {
  std::list<T> ret;
  Node* current{_head};
  while(current != nullptr) {
    ret.push_back(current->data);
    current = current->next;
  }
  return ret;
}

// Doubly-linked List implementation (without sentinels)
template<typename T>
class DoublyLinkedList : public List<T> {
public:
  DoublyLinkedList(); // O(1)
  DoublyLinkedList(const DoublyLinkedList& o); // O(n)
  DoublyLinkedList(DoublyLinkedList&& o); // O(1)
  ~DoublyLinkedList(); // O(n)

  DoublyLinkedList& operator=(const DoublyLinkedList& l);

  T& value_at(std::size_t i); // O(i)
  const T& value_at(std::size_t i) const; // O(i)
  T& front(); // O(1)
  T& back(); // O(1)
  const T& front() const; // O(1)
  const T& back() const; // O(1)

  bool empty() const; // O(1)
  std::size_t size() const; // O(1)

  void insert_at(std::size_t i, const T& v); // O(i)
  void insert_at(std::size_t i, T&& v); // O(i)
  void push_front(const T& v); // O(1)
  void push_front(T&& v); // O(1)
  void push_back(const T& v); // O(1)
  void push_back(T&& v); // O(1)

  T remove_at(std::size_t i); // O(i)
  T pop_front(); // O(1)
  T pop_back(); // O(1)

  void clear(); // O(n)
  std::list<T> to_std_list() const; // O(n)

private:
  struct Node {
    Node(const T& v, Node* n = nullptr, Node* p = nullptr);
    Node(T&& prv, Node* n = nullptr, Node* p = nullptr);
    T data;
    Node* prev;
    Node* next;
  };

  Node* _head;
  Node* _tail;
  std::size_t _size;

  Node* get_node_at(std::size_t i) const;
  void push_all(const DoublyLinkedList& o);
};

template<typename T>
DoublyLinkedList<T>::Node::Node(const T& v, Node* n, Node* p) : data(v), prev(p), next(n) {
}

template<typename T>
DoublyLinkedList<T>::Node::Node(T&& prv, Node* n, Node* p) : data(std::move(prv)), prev(p), next(n) {
}

template<typename T>
DoublyLinkedList<T>::DoublyLinkedList() : _head(nullptr), _tail(nullptr), _size(0) {
}

template<typename T>
DoublyLinkedList<T>::DoublyLinkedList(const DoublyLinkedList& o) : _head(nullptr), _tail(nullptr), _size(0) {
  push_all(o);
}

template<typename T>
DoublyLinkedList<T>::DoublyLinkedList(DoublyLinkedList&& o) : _head(o._head), _tail(o._tail), _size(o._size) {
  o._head = nullptr;
  o._tail = nullptr;
  o._size = 0;
}

template<typename T>
DoublyLinkedList<T>& DoublyLinkedList<T>::operator=(const DoublyLinkedList& l) {
  if(this != &l) {
    clear();
    push_all(l);
  }
  return *this;
}

template<typename T>
void DoublyLinkedList<T>::push_all(const DoublyLinkedList& o) {
  Node* oit = o._head;
  Node** current = &_head;
  Node* last = nullptr;
  while(oit != nullptr) {
    *current = new Node(oit->data, nullptr, last);
    last = *current;
    _size++;
    // next pointer of current will be updated in the following cycle
    current = &((*current)->next);
    oit = oit->next;
  }
  _tail = last;
}

template<typename T>
bool DoublyLinkedList<T>::empty() const {
  return _head == nullptr;
}

template<typename T>
std::size_t DoublyLinkedList<T>::size() const {
  return _size;
}

template<typename T>
DoublyLinkedList<T>::~DoublyLinkedList() {
  clear();
}

template<typename T>
T& DoublyLinkedList<T>::value_at(std::size_t i) {
  assert(i >= 0 && i < size());
  return get_node_at(i)->data;
}

template<typename T>
const T& DoublyLinkedList<T>::value_at(std::size_t i) const {
  assert(i >= 0 && i < size());
  return get_node_at(i)->data;
}

template<typename T>
T& DoublyLinkedList<T>::front() {
  return value_at(0);
}

template<typename T>
T& DoublyLinkedList<T>::back() {
  return value_at(size() - 1);
}

template<typename T>
const T& DoublyLinkedList<T>::front() const {
  return value_at(0);
}

template<typename T>
const T& DoublyLinkedList<T>::back() const {
  return value_at(size() - 1);
}

template<typename T>
typename DoublyLinkedList<T>::Node*
DoublyLinkedList<T>::get_node_at(std::size_t i) const {
  assert(i >= 0 && i < size());

  if(i == size() - 1) {
    return _tail;
  }

  // we could start from _head or _tail depending on the shortest distance
  // to i, but it is not really worth it
  Node* current = _head;
  while(i > 0) {
    current = current->next;
    i--;
  }
  return current;
}

template<typename T>
void DoublyLinkedList<T>::clear() {
  while(!empty()) {
    pop_front();
  }
}

template<typename T>
void DoublyLinkedList<T>::insert_at(std::size_t i, const T& v) {
  assert(i >= 0 && i <= size());

  if(size() == 0) {
    // we have to update both head and tail
    _head = new Node(v);
    _tail = _head;
  } else if(i == 0) {
    // at least 1 element and inserting at head, only head needs to be updated
    Node* old_head = _head;
    _head = new Node(v, old_head);
    old_head->prev = _head;
  } else if(i == size()) {
    // at least 1 element and inserting after tail, only tail needs to be updated
    Node* old_tail = _tail;
    _tail = new Node(v, nullptr, old_tail);
    old_tail->next = _tail;
  } else {
    // at least 2 elements and not inserting at head nor after tail
    // element at i exists and has at least one element before
    Node* node_at = get_node_at(i);
    Node* before = node_at->prev;
    before->next = new Node(v, node_at, before);
    node_at->prev = before->next;
  }
  _size++;
}

// find out how to de-duplicate code regarding lvalues and rvalue references
template<typename T>
void DoublyLinkedList<T>::insert_at(std::size_t i, T&& v) {
  assert(i >= 0 && i <= size());

  if(size() == 0) {
    // we have to update both head and tail
    _head = new Node(std::move(v));
    _tail = _head;
  } else if(i == 0) {
    // at least 1 element and inserting at head, only head needs to be updated
    Node* old_head = _head;
    _head = new Node(std::move(v), old_head);
    old_head->prev = _head;
  } else if(i == size()) {
    // at least 1 element and inserting after tail, only tail needs to be updated
    Node* old_tail = _tail;
    _tail = new Node(std::move(v), nullptr, old_tail);
    old_tail->next = _tail;
  } else {
    // at least 2 elements and not inserting at head nor after tail
    // element at i exists and has at least one element before
    Node* node_at = get_node_at(i);
    Node* before = node_at->prev;
    before->next = new Node(std::move(v), node_at, before);
    node_at->prev = before->next;
  }
  _size++;
}

template<typename T>
T DoublyLinkedList<T>::remove_at(std::size_t i) {
  assert(i >= 0 && i < size());

  if(size() == 1) {
    // we have to update both head and tail
    T ret{std::move(_head->data)};
    delete _head;
    _head = nullptr;
    _tail = nullptr;
    _size--;
    return ret;
  } else if(i == 0) {
    // at least 2 elements and removing head, head and next need to be updated
    T ret{std::move(_head->data)};
    Node* new_head = _head->next;
    delete _head;
    new_head->prev = nullptr;
    _head = new_head;
    _size--;
    return ret;
  } else if(i == size() - 1) {
    // at least 2 elements and removing tail, tail and prev need to be updated
    T ret{std::move(_tail->data)};
    Node* new_tail = _tail->prev;
    delete _tail;
    new_tail->next = nullptr;
    _tail = new_tail;
    _size--;
    return ret;
  } else {
    // at least 3 elements, @i exists and has surrounding elements
    Node* node_at = get_node_at(i);
    Node* before = node_at->prev;
    Node* after = node_at->next;
    T ret{std::move(node_at->data)};
    delete node_at;
    before->next = after;
    after->prev = before;
    _size--;
    return ret;
  }
}

template<typename T>
void DoublyLinkedList<T>::push_back(const T& v) {
  return insert_at(size(), v);
}

template<typename T>
void DoublyLinkedList<T>::push_back(T&& v) {
  return insert_at(size(), v);
}

template<typename T>
void DoublyLinkedList<T>::push_front(const T& v) {
  return insert_at(0, v);
}

template<typename T>
void DoublyLinkedList<T>::push_front(T&& v) {
  return insert_at(0, v);
}

template<typename T>
T DoublyLinkedList<T>::pop_front() {
  return remove_at(0);
}

template<typename T>
T DoublyLinkedList<T>::pop_back() {
  return remove_at(size() - 1);
}

template<typename T>
std::list<T> DoublyLinkedList<T>::to_std_list() const {
  std::list<T> ret;
  Node* current{_head};
  while(current != nullptr) {
    ret.push_back(current->data);
    current = current->next;
  }
  return ret;
}

#endif


text:
package sun.lwawt;

import java.awt.*;

import sun.awt.CausedFocusEvent;
import sun.java2d.SurfaceData;

// TODO Is it worth to generify this interface, like that:
//
// public interface PlatformWindow<WindowType extends Window>
//
// ?

public interface PlatformWindow {

    /*
     * Delegate initialization (create native window and all the
     * related resources).
     */
    public void initialize(Window target, LWWindowPeer peer, PlatformWindow owner);

    /*
     * Delegate shutdown (dispose native window and all the
     * related resources).
     */
    public void dispose();

    /*
     * Shows or hides the window.
     */
    public void setVisible(boolean visible);

    /*
     * Sets the window title
     */
    public void setTitle(String title);

    /*
     * Sets the window bounds. Called when user changes window bounds
     * with setSize/setLocation/setBounds/reshape methods.
     */
    public void setBounds(int x, int y, int w, int h);

    /*
     * Returns the graphics device where the window is.
     */
    public GraphicsDevice getGraphicsDevice();

    /*
     * Returns the location of the window.
     */
    public Point getLocationOnScreen();

    /*
     * Returns the window insets.
     */
    public Insets getInsets();

    /*
     * Returns the metrics for a given font.
     */
    public FontMetrics getFontMetrics(Font f);

    /*
     * Get the SurfaceData for the window.
     */
    public SurfaceData getScreenSurface();

    /*
     * Revalidates the window's current SurfaceData and returns
     * the newly created one.
     */
    public SurfaceData replaceSurfaceData();

    public void setModalBlocked(boolean blocked);

    public void toFront();

    public void toBack();

    public void setMenuBar(MenuBar mb);

    public void setAlwaysOnTop(boolean value);

    public PlatformWindow getTopmostPlatformWindowUnderMouse();

    public void updateFocusableWindowState();

    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);

    public boolean requestWindowFocus();

    /*
     * Returns true only when called on a frame/dialog when it's natively focused.
     */
    public boolean isActive();

    public void setResizable(boolean resizable);

    /**
     * Applies the minimum and maximum size to the platform window.
     */
    public void setSizeConstraints(int minW, int minH, int maxW, int maxH);

    /**
     * Transforms the given Graphics object according to the native
     * implementation traits (insets, etc.).
     */
    public Graphics transformGraphics(Graphics g);

    /*
     * Installs the images for particular window.
     */
    public void updateIconImages();

    public void setOpacity(float opacity);

    public void setOpaque(boolean isOpaque);

    public void enterFullScreenMode();

    public void exitFullScreenMode();

    public boolean isFullScreenMode();

    public void setWindowState(int windowState);

    public long getLayerPtr();

    public LWWindowPeer getPeer();

    public boolean isUnderMouse();
}


text:
package org.seasar.doma.internal.apt.processor.dao;

import org.seasar.doma.Dao;
import org.seasar.doma.Select;

@SuppressWarnings("deprecation")
@Dao(config = MyConfig.class)
public interface RawTypeParamDao {

  @SuppressWarnings("rawtypes")
  @Select
  int select(Height height);
}


text:
require 'rails_helper'

RSpec.describe BusinessRolesController, type: :routing do
  describe 'routing' do
    it 'routes to #index' do
      expect(get: '/business_roles').to route_to('business_roles#index')
    end

    it 'routes to #new' do
      expect(get: '/business_roles/new').to route_to('business_roles#new')
    end

    it 'routes to #show' do
      expect(get: '/business_roles/1').to route_to('business_roles#show', id: '1')
    end

    it 'routes to #edit' do
      expect(get: '/business_roles/1/edit').to route_to('business_roles#edit', id: '1')
    end

    it 'routes to #create' do
      expect(post: '/business_roles').to route_to('business_roles#create')
    end

    it 'routes to #update' do
      expect(put: '/business_roles/1').to route_to('business_roles#update', id: '1')
    end

    it 'routes to #destroy' do
      expect(delete: '/business_roles/1').to route_to('business_roles#destroy', id: '1')
    end

    it 'routes to #create_user' do
      expect(get: '/business_roles/1/create_user').to route_to('business_roles#create_user', id: '1')
    end
    # post :update_user
  end
end


text:
BUCKET=$EXAMPLE_ZOO_ARTIFACTS_BUCKET
PROJECT_ID=$EXAMPLE_ZOO_PROJECT_ID

PACKAGE_PATH="trainer"
MODULE_NAME="trainer.logistic_regression"

now=$(date +"%Y%m%d_%H%M%S")
JOB_NAME="logistic_regression_$now"

JOB_DIR=$BUCKET"/"$JOB_NAME"/"

gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS

gcloud ai-platform jobs submit training $JOB_NAME \
    --job-dir $JOB_DIR  \
    --package-path $PACKAGE_PATH \
    --module-name $MODULE_NAME \
    --region us-central1 \
    --config config.yaml \
    --runtime-version 1.14 \
    --python-version 2.7 \
    --project $PROJECT_ID \
    -- \
    --model_dir=$JOB_DIR \
    --num_examples=32 \
    --batch_size=8 \
    --max_steps=50


text:
module RuboCop
  module Formatter
    # This formatter formats report data using the Test Anything Protocol.
    # TAP allows for to communicate tests results in a language agnostics way.
    class TapFormatter < ClangStyleFormatter
      def started(target_files)
        super
        @progress_count = 1
        output.puts "1..#{target_files.size}"
      end

      def file_finished(file, offenses)
        if offenses.empty?
          output.puts "ok #{@progress_count} - #{smart_path(file)}"
        else
          output.puts "not ok #{@progress_count} - #{smart_path(file)}"

          count_stats(offenses)
          report_file(file, offenses)
        end

        @progress_count += 1
      end

      private

      def report_line(location)
        source_line = location.source_line

        if location.first_line == location.last_line
          output.puts("# #{source_line}")
        else
          output.puts("# #{source_line} #{yellow(ELLIPSES)}")
        end
      end

      def report_highlighted_area(highlighted_area)
        output.puts("# #{' ' * highlighted_area.begin_pos}" \
                    "#{'^' * highlighted_area.size}")
      end

      def report_offense(file, offense)
        output.printf(
          "# %<path>s:%<line>d:%<column>d: %<severity>s: %<message>s\n",
          path: cyan(smart_path(file)),
          line: offense.line,
          column: offense.real_column,
          severity: colored_severity_code(offense),
          message: message(offense)
        )

        begin
          return unless valid_line?(offense)

          report_line(offense.location)
          report_highlighted_area(offense.highlighted_area)
        rescue IndexError
          # range is not on a valid line; perhaps the source file is empty
        end
      end

      def annotate_message(msg)
        msg.gsub(/`(.*?)`/, '\1')
      end

      def message(offense)
        message =
          if offense.corrected_with_todo?
            '[Todo] '
          elsif offense.corrected?
            '[Corrected] '
          else
            ''
          end

        "#{message}#{annotate_message(offense.message)}"
      end
    end
  end
end


text:
module.exports = function (grunt) {
  var path = require('path');
  var fs = require('fs');
  var async = require('async');
  var Zip = require('node-native-zip');

  /**
  * Create a zip file with a customisable filename.
  *
  * Deps: node-native-zip, async
  *
  * Format of the output filename is:
  *
  *   <appName>_<version>_git@<commitID>_YYYY-MM-DD_HHMMSS_<suffix>.zip
  *
  * The git, version and suffix parts are optional (see below for
  * configuration).
  *
  * Configuration options:
  *
  *   appName - the name of the application; used as the base filename
  *   files - glob of files to zip TODO allow array of globs
  *   suffix - zip file suffix (default 'zip')
  *   outDir - output directory to put the zipfile into
  *   version - application version
  *   stripPrefix - if dir has a folder hierarchy inside it, specify
  *                 the prefix to strip from all paths, to remove
  *                 the embedded folders (default = '')
  *   addGitCommitId - if the project is a git repo, this includes the
  *                    8 character variant of the last commit ID as
  *                    part of the filename, e.g.
  *                    app_git@81a131a2_2012-11-01_1151.zip
  *                    (default = false)
  *
  * Example configuration:
  *
  * grunt.initConfig({
  *   package: {
  *     wgt: {
  *       appName: 'app',
  *       suffix: 'wgt',
  *       version: '0.1.0',
  *       addGitCommitId: true,
  *       files: 'build/dist/**',
  *       stripPrefix: 'build/dist',
  *       outDir: 'build'
  *     }
  *   }
  * });
  *
  * In this example, we zip up the files matching build/dist/**.
  * Inside the zip file, the directory structure has the build/dist
  * prefix stripped, so our zipfile structure matches the structure
  * under the build/dist directory. The zipfile goes into the build/
  * directory. The output zipfile name also contains the latest
  * git commit ID and has the suffix .zip
  *
  * A pre-suffix is added if you pass an identifier string to this task
  * when calling it, e.g.
  *
  *   grunt package:TEST
  *
  * will produce an output file with name like
  *
  *   app_2012-11-01_1149_TEST.zip
  *
  * To do this as part of your own custom task, modify your
  * gruntfile like this:
  *
  * grunt.registerTask('pkg', 'create package', function (identifier) {
  *    // ...do other tasks here, e.g. minify and copy files for distribution...
  *
  *    var packageTask = (identifier ? 'package:' + identifier : 'package');
  *    grunt.task.run(packageTask);
  *  });
  *
  * then call it with pkg:TEST, where TEST is the string
  * you want to append to the output filename.
  */
  grunt.registerMultiTask('package', 'Zip files with custom zipfile name', function (identifier) {
    var appName = this.data.appName;
    var version = this.data.version;
    var files = this.data.files;
    var suffix = this.data.suffix || 'zip';
    var outDir = this.data.outDir || '.';
    var addGitCommitId = !!this.data.addGitCommitId;

    // this is removed from the path of each file as it is added to the zip
    var stripPrefix = this.data.stripPrefix || '';
    stripPrefix = new RegExp('^' + stripPrefix);

    if (!appName) {
      grunt.fatal('package task requires appName argument');
    }

    if (!version) {
      grunt.fatal('package task requires version argument (x.x.x)');
    }

    if (!files) {
      grunt.fatal('package task requires dir argument (directory to zip)');
    }

    files = grunt.file.expand(files);

    var done = this.async();

    var outFile = appName;

    // get the latest commit ID as an 8-character string;
    // if not a git repo, returns '' and logs an error;
    // receiver is a function with the signature receiver(err, result),
    // where err is null if no error occurred and result is the commit ID
    var gitCommitId = function (receiver) {
      grunt.util.spawn(
        {
          cmd: "git",
          args: ["log", "-n1", "--format=format:'%h'"]
        },

        function (err, result) {
          if (err) {
            receiver(true, '');
          }
          else {
            receiver(null, result.stdout.replace(/'/g, ''));
          }
        }
      );
    };

    var isFile = function (path) {
      if (!fs.existsSync(path) || fs.statSync(path).isDirectory()) {
        return false;
      }

      return true;
    };

    var packFiles = function (outfile, infiles, cb) {
      var zipfile = new Zip();
      var buffer;

      async.forEachSeries(
        infiles,
        function (file, next) {
          if (isFile(file)) {
            var filename = file.replace(stripPrefix, '');

            grunt.log.writeln('adding ' + file + ' to package as ' + filename);

            buffer = fs.readFileSync(file);

            zipfile.add(filename, buffer);

            next();
          }
          else {
            next();
          }
        },
        function (err, result) {
          grunt.log.writeln('\npackage written to:\n' + outfile);
          buffer = zipfile.toBuffer();
          fs.writeFile(outfile, buffer, cb);
        }
      );
    };

    var receiver = function (err, result) {
      if (version) {
        outFile += '_' + version;
      }

      if (result) {
        outFile += '_git@' + result;
      }

      outFile += '_' + grunt.template.today("yyyy-mm-dd_HHMMss");

      if (identifier) {
        outFile += '_' + identifier;
      }

      outFile += '.' + suffix.replace(/^\./, '');
      outFile = path.join(outDir, outFile);

      packFiles(outFile, files, done);
    };

    // append git commit ID to the package name
    if (addGitCommitId) {
      gitCommitId(receiver);
    }
    else {
      receiver(false, null);
    }
  });

};


text:
require 'relative_time/in_words'
require 'relative_time/version'

module RelativeTime
  def self.in_words(date_to, date_from = Time.now, locale: :en)
    InWords.new(locale: locale).(date_to, date_from)
  end
end