Added review statistics management (#2910).
This commit is contained in:
parent
f3f18fc395
commit
cf119c5b92
313
resources/reviewstats.csv
Normal file
313
resources/reviewstats.csv
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
20110930-12h00 6
|
||||||
|
20111007-12h00 6
|
||||||
|
20111014-12h00 8
|
||||||
|
20111021-12h00 5
|
||||||
|
20111028-12h00 10
|
||||||
|
20111104-12h00 8
|
||||||
|
20111111-12h00 3
|
||||||
|
20111118-12h00 7
|
||||||
|
20111125-12h00 7
|
||||||
|
20111202-12h00 7
|
||||||
|
20111209-12h00 3
|
||||||
|
20111216-12h00 7
|
||||||
|
20111223-12h00 7
|
||||||
|
20111230-12h00 7
|
||||||
|
20120106-12h00 8
|
||||||
|
20120113-12h00 6
|
||||||
|
20120120-12h00 7
|
||||||
|
20120217-12h00 8
|
||||||
|
20120302-12h00 10
|
||||||
|
20120309-12h00 8
|
||||||
|
20120316-12h00 3
|
||||||
|
20120323-12h00 6
|
||||||
|
20120330-12h00 6
|
||||||
|
20120406-12h00 7
|
||||||
|
20120413-12h00 7
|
||||||
|
20120420-12h00 5
|
||||||
|
20120504-12h00 8
|
||||||
|
20120511-12h00 6
|
||||||
|
20120518-12h00 4
|
||||||
|
20120525-12h00 7
|
||||||
|
20120601-12h00 3
|
||||||
|
20120608-12h00 6
|
||||||
|
20120615-12h00 7
|
||||||
|
20120622-12h00 9
|
||||||
|
20120629-12h00 4
|
||||||
|
20120706-12h00 6
|
||||||
|
20120720-12h00 8
|
||||||
|
20120727-12h00 5
|
||||||
|
20120803-12h00 6
|
||||||
|
20120810-12h00 6
|
||||||
|
20120817-12h00 6
|
||||||
|
20120824-12h00 8
|
||||||
|
20120831-12h00 10
|
||||||
|
20120907-12h00 12
|
||||||
|
20120914-12h00 8
|
||||||
|
20120921-12h00 4
|
||||||
|
20120928-12h00 8
|
||||||
|
20121012-12h00 6
|
||||||
|
20121019-12h00 7
|
||||||
|
20121026-12h00 7
|
||||||
|
20121102-12h00 8
|
||||||
|
20121109-12h00 7
|
||||||
|
20121116-12h00 8
|
||||||
|
20121123-12h00 5
|
||||||
|
20121130-12h00 13
|
||||||
|
20121207-12h00 10
|
||||||
|
20121214-12h00 14
|
||||||
|
20121221-12h00 10
|
||||||
|
20121228-12h00 4
|
||||||
|
20130104-12h00 7
|
||||||
|
20130111-12h00 6
|
||||||
|
20130118-12h00 10
|
||||||
|
20130125-12h00 10
|
||||||
|
20130201-12h00 8
|
||||||
|
20130208-12h00 11
|
||||||
|
20130215-12h00 6
|
||||||
|
20130222-12h00 7
|
||||||
|
20130301-12h00 8
|
||||||
|
20130308-12h00 4
|
||||||
|
20130315-12h00 6
|
||||||
|
20130322-12h00 4
|
||||||
|
20130329-12h00 7
|
||||||
|
20130405-12h00 10
|
||||||
|
20130412-12h00 8
|
||||||
|
20130419-12h00 6
|
||||||
|
20130426-12h00 5
|
||||||
|
20130503-12h00 8
|
||||||
|
20130510-12h00 3
|
||||||
|
20130517-12h00 8
|
||||||
|
20130524-12h00 9
|
||||||
|
20130531-12h00 7
|
||||||
|
20130607-12h00 8
|
||||||
|
20130614-12h00 9
|
||||||
|
20130628-12h00 9
|
||||||
|
20130705-12h00 9
|
||||||
|
20130712-12h00 7
|
||||||
|
20130719-12h00 11
|
||||||
|
20130726-12h00 7
|
||||||
|
20130802-12h00 11
|
||||||
|
20130809-12h00 10
|
||||||
|
20130816-12h00 6
|
||||||
|
20130823-12h00 6
|
||||||
|
20130830-12h00 6
|
||||||
|
20130906-12h00 11
|
||||||
|
20130913-12h00 8
|
||||||
|
20130920-12h00 6
|
||||||
|
20130927-12h00 6
|
||||||
|
20131004-12h00 3
|
||||||
|
20131011-12h00 5
|
||||||
|
20131018-12h00 5
|
||||||
|
20131025-12h00 3
|
||||||
|
20131101-12h00 6
|
||||||
|
20131108-12h00 4
|
||||||
|
20131115-12h00 3
|
||||||
|
20131122-12h00 6
|
||||||
|
20131129-12h00 2
|
||||||
|
20131206-12h00 6
|
||||||
|
20131213-12h00 5
|
||||||
|
20131220-12h00 2
|
||||||
|
20131227-12h00 5
|
||||||
|
20140103-12h00 4
|
||||||
|
20140110-12h00 5
|
||||||
|
20140117-12h00 8
|
||||||
|
20140124-12h00 6
|
||||||
|
20140131-12h00 7
|
||||||
|
20140207-12h00 5
|
||||||
|
20140214-12h00 6
|
||||||
|
20140221-12h00 6
|
||||||
|
20140228-12h00 8
|
||||||
|
20140307-12h00 5
|
||||||
|
20140314-12h00 6
|
||||||
|
20140321-12h00 5
|
||||||
|
20140328-12h00 6
|
||||||
|
20140404-12h00 6
|
||||||
|
20140411-12h00 5
|
||||||
|
20140418-12h00 6
|
||||||
|
20140425-12h00 5
|
||||||
|
20140502-12h00 5
|
||||||
|
20140509-12h00 6
|
||||||
|
20140516-12h00 4
|
||||||
|
20140523-12h00 2
|
||||||
|
20140613-12h00 6
|
||||||
|
20140620-12h00 4
|
||||||
|
20140627-12h00 5
|
||||||
|
20140704-12h00 6
|
||||||
|
20140711-12h00 7
|
||||||
|
20140718-12h00 7
|
||||||
|
20140725-12h00 3
|
||||||
|
20140801-12h00 6
|
||||||
|
20140808-12h00 5
|
||||||
|
20140822-12h00 4
|
||||||
|
20140829-12h00 7
|
||||||
|
20140905-12h00 6
|
||||||
|
20140912-12h00 5
|
||||||
|
20140919-12h00 5
|
||||||
|
20140926-12h00 3
|
||||||
|
20141010-12h00 5
|
||||||
|
20141017-12h00 7
|
||||||
|
20141024-12h00 6
|
||||||
|
20141031-12h00 6
|
||||||
|
20141107-12h00 3
|
||||||
|
20141114-12h00 7
|
||||||
|
20141121-12h00 7
|
||||||
|
20141128-12h00 6
|
||||||
|
20141205-12h00 7
|
||||||
|
20141212-12h00 7
|
||||||
|
20141219-12h00 6
|
||||||
|
20150109-12h00 4
|
||||||
|
20150116-12h00 1
|
||||||
|
20150123-12h00 4
|
||||||
|
20150130-12h00 6
|
||||||
|
20150206-12h00 4
|
||||||
|
20150213-12h00 2
|
||||||
|
20150220-12h00 7
|
||||||
|
20150227-12h00 4
|
||||||
|
20150306-12h00 11
|
||||||
|
20150313-12h00 10
|
||||||
|
20150320-12h00 8
|
||||||
|
20150327-12h00 5
|
||||||
|
20150403-12h00 6
|
||||||
|
20150410-12h00 8
|
||||||
|
20150417-12h00 4
|
||||||
|
20150424-12h00 3
|
||||||
|
20150507-12h00 5
|
||||||
|
20150515-12h00 8
|
||||||
|
20150522-12h00 7
|
||||||
|
20150529-12h00 5
|
||||||
|
20150605-12h00 10
|
||||||
|
20150612-12h00 6
|
||||||
|
20150619-12h00 3
|
||||||
|
20150626-12h00 5
|
||||||
|
20150703-12h00 5
|
||||||
|
20150710-12h00 5
|
||||||
|
20150717-12h00 6
|
||||||
|
20150724-12h00 7
|
||||||
|
20150731-12h00 5
|
||||||
|
20150807-12h00 4
|
||||||
|
20150814-12h00 4
|
||||||
|
20150828-12h00 5
|
||||||
|
20150904-12h00 5
|
||||||
|
20150918-12h00 6
|
||||||
|
20150925-12h00 5
|
||||||
|
20151002-12h00 7
|
||||||
|
20151009-12h00 5
|
||||||
|
20151016-12h00 8
|
||||||
|
20151023-12h00 6
|
||||||
|
20151030-12h00 8
|
||||||
|
20151106-12h00 5
|
||||||
|
20151113-12h00 9
|
||||||
|
20151120-12h00 9
|
||||||
|
20151127-12h00 7
|
||||||
|
20151204-12h00 10
|
||||||
|
20151211-12h00 7
|
||||||
|
20151218-12h00 10
|
||||||
|
20160108-12h00 8
|
||||||
|
20160219-12h00 6
|
||||||
|
20160226-12h00 9
|
||||||
|
20160318-12h00 6
|
||||||
|
20160401-12h00 6
|
||||||
|
20160408-12h00 8
|
||||||
|
20160415-12h00 6
|
||||||
|
20160422-12h00 7
|
||||||
|
20160429-12h00 7
|
||||||
|
20160506-12h00 7
|
||||||
|
20160513-12h00 6
|
||||||
|
20160520-12h00 6
|
||||||
|
20160527-12h00 8
|
||||||
|
20160603-12h00 3
|
||||||
|
20160610-12h00 4
|
||||||
|
20160617-12h00 7
|
||||||
|
20160624-12h00 6
|
||||||
|
20160701-12h00 6
|
||||||
|
20160708-12h00 7
|
||||||
|
20160715-12h00 4
|
||||||
|
20160722-12h00 6
|
||||||
|
20160805-12h00 4
|
||||||
|
20160812-12h00 3
|
||||||
|
20160819-12h00 4
|
||||||
|
20160826-12h00 4
|
||||||
|
20160902-12h00 6
|
||||||
|
20160909-12h00 7
|
||||||
|
20160916-12h00 7
|
||||||
|
20160923-12h00 7
|
||||||
|
20160930-12h00 4
|
||||||
|
20161007-12h00 6
|
||||||
|
20161021-12h00 7
|
||||||
|
20161028-12h00 6
|
||||||
|
20161104-12h00 7
|
||||||
|
20161110-12h00 7
|
||||||
|
20161118-12h00 7
|
||||||
|
20161125-12h00 7
|
||||||
|
20161202-12h00 4
|
||||||
|
20161209-12h00 7
|
||||||
|
20161216-12h00 9
|
||||||
|
20161223-12h00 5
|
||||||
|
20170106-12h00 7
|
||||||
|
20170113-12h00 4
|
||||||
|
20170120-12h00 8
|
||||||
|
20170127-12h00 7
|
||||||
|
20170203-12h00 6
|
||||||
|
20170210-12h00 6
|
||||||
|
20170217-12h00 8
|
||||||
|
20170224-12h00 8
|
||||||
|
20170303-12h00 7
|
||||||
|
20170310-12h00 7
|
||||||
|
20170317-12h00 4
|
||||||
|
20170324-12h00 6
|
||||||
|
20170331-12h00 5
|
||||||
|
20170407-12h00 4
|
||||||
|
20170414-12h00 4
|
||||||
|
20170421-12h00 9
|
||||||
|
20170428-12h00 7
|
||||||
|
20170505-12h00 6
|
||||||
|
20170512-12h00 7
|
||||||
|
20170519-12h00 6
|
||||||
|
20170526-12h00 5
|
||||||
|
20170602-12h00 8
|
||||||
|
20170609-12h00 10
|
||||||
|
20170616-12h00 9
|
||||||
|
20170623-12h00 7
|
||||||
|
20170630-12h00 5
|
||||||
|
20170707-12h00 12
|
||||||
|
20170713-12h00 4
|
||||||
|
20170721-12h00 6
|
||||||
|
20170727-12h00 6
|
||||||
|
20170818-12h00 5
|
||||||
|
20170825-12h00 3
|
||||||
|
20170901-12h00 6
|
||||||
|
20170908-12h00 5
|
||||||
|
20170915-12h00 7
|
||||||
|
20170922-12h00 5
|
||||||
|
20170929-12h00 10
|
||||||
|
20171006-12h00 9
|
||||||
|
20171013-12h00 9
|
||||||
|
20171020-12h00 7
|
||||||
|
20171027-12h00 8
|
||||||
|
20171103-12h00 10
|
||||||
|
20171110-12h00 10
|
||||||
|
20171117-12h00 8
|
||||||
|
20171124-12h00 8
|
||||||
|
20171201-12h00 9
|
||||||
|
20171208-12h00 10
|
||||||
|
20171215-12h00 11
|
||||||
|
20171222-12h00 7
|
||||||
|
20180105-12h00 7
|
||||||
|
20180112-12h00 10
|
||||||
|
20180118-12h00 1
|
||||||
|
20180119-12h00 12
|
||||||
|
20180126-12h00 10
|
||||||
|
20180202-12h00 9
|
||||||
|
20180209-12h00 8 17
|
||||||
|
20180216-12h00 8 16
|
||||||
|
20180223-12h00 5 14
|
||||||
|
20180302-12h00 6 19
|
||||||
|
20180309-12h00 11 20
|
||||||
|
20180316-12h00 9 19
|
||||||
|
20180323-12h00 9 17
|
||||||
|
20180330-12h00 10 19
|
||||||
|
20180406-12h00 9 17
|
||||||
|
20180413-12h00 11 15
|
||||||
|
20180420-12h00 6 17
|
||||||
|
20180427-12h00 7 17
|
||||||
|
20180504-12h00 7 17
|
Can't render this file because it has a wrong number of fields in line 62.
|
@ -40,6 +40,10 @@ import org.april.hebdobot.model.review.IndividualTopic;
|
|||||||
import org.april.hebdobot.model.review.Message;
|
import org.april.hebdobot.model.review.Message;
|
||||||
import org.april.hebdobot.model.review.Review;
|
import org.april.hebdobot.model.review.Review;
|
||||||
import org.april.hebdobot.model.review.Topic;
|
import org.april.hebdobot.model.review.Topic;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewData;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewDatas;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewDatasFile;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewStatsReporter;
|
||||||
import org.april.hebdobot.pastebin.PastebinClient;
|
import org.april.hebdobot.pastebin.PastebinClient;
|
||||||
import org.april.hebdobot.pastebin.PastebinSettings;
|
import org.april.hebdobot.pastebin.PastebinSettings;
|
||||||
import org.april.hebdobot.pastebin.Private;
|
import org.april.hebdobot.pastebin.Private;
|
||||||
@ -364,6 +368,36 @@ public class Hebdobot extends PircBot
|
|||||||
String participants = StringUtils.join(this.review.getParticipants(), " ");
|
String participants = StringUtils.join(this.review.getParticipants(), " ");
|
||||||
sendMessage("% " + participants + ", pensez à noter votre bénévalo : http://www.april.org/my?action=benevalo");
|
sendMessage("% " + participants + ", pensez à noter votre bénévalo : http://www.april.org/my?action=benevalo");
|
||||||
|
|
||||||
|
// Display statistics. This feature has to not break
|
||||||
|
// Hebdobot.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File reviewDataFile = new File(this.reviewDirectory, "reviewstats.csv");
|
||||||
|
if (reviewDataFile.exists())
|
||||||
|
{
|
||||||
|
ReviewDatas datas = ReviewDatasFile.load(reviewDataFile);
|
||||||
|
datas.clean();
|
||||||
|
sendMessage("% " + ReviewStatsReporter.reportNewMaxUserCount(datas, this.review.getParticipants().size()));
|
||||||
|
ReviewData currentReview = new ReviewData(LocalDateTime.now(), this.review.getParticipants().size(),
|
||||||
|
(int) this.review.getDurationInMinutes());
|
||||||
|
datas.add(currentReview);
|
||||||
|
sendMessage("% " + ReviewStatsReporter.reportUserCount(datas, currentReview.getUserCount()));
|
||||||
|
sendMessage("% " + ReviewStatsReporter.reportDuration(datas, currentReview.getUserCount()));
|
||||||
|
|
||||||
|
ReviewDatasFile.append(reviewDataFile, currentReview);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("Statistic file not found [{}]", reviewDataFile.getAbsolutePath());
|
||||||
|
sendMessage("% Fichier de statistiques absent.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.warn("Exception during statistics work.", exception);
|
||||||
|
sendMessage("% Impossible d'afficher des statistiques.");
|
||||||
|
}
|
||||||
|
|
||||||
sendMessage("% Fin de la revue hebdomadaire");
|
sendMessage("% Fin de la revue hebdomadaire");
|
||||||
sendMessage(this.review.getOwner(), "Revue finie.");
|
sendMessage(this.review.getOwner(), "Revue finie.");
|
||||||
|
|
||||||
|
301
src/org/april/hebdobot/model/stats/IntegerBoard.java
Normal file
301
src/org/april/hebdobot/model/stats/IntegerBoard.java
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import fr.devinsy.util.strings.StringList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Integers.
|
||||||
|
*/
|
||||||
|
public class IntegerBoard implements Iterable<IntegerStat>
|
||||||
|
{
|
||||||
|
private Map<Integer, IntegerStat> integers;
|
||||||
|
private boolean isUptodate;
|
||||||
|
private IntegerStats board;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new distribution.
|
||||||
|
*/
|
||||||
|
public IntegerBoard()
|
||||||
|
{
|
||||||
|
this.integers = new HashMap<Integer, IntegerStat>(30);
|
||||||
|
this.isUptodate = false;
|
||||||
|
this.board = new IntegerStats(this.integers.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return true, if successful
|
||||||
|
*/
|
||||||
|
public void add(final Integer value)
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
IntegerStat stat = this.integers.get(value);
|
||||||
|
if (stat == null)
|
||||||
|
{
|
||||||
|
stat = new IntegerStat(value);
|
||||||
|
this.integers.put(value, stat);
|
||||||
|
}
|
||||||
|
|
||||||
|
stat.inc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return the integer stat
|
||||||
|
*/
|
||||||
|
public IntegerStat get(final int value)
|
||||||
|
{
|
||||||
|
IntegerStat result;
|
||||||
|
|
||||||
|
result = this.integers.get(value);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the average.
|
||||||
|
*
|
||||||
|
* @return the average
|
||||||
|
*/
|
||||||
|
public double getAverage()
|
||||||
|
{
|
||||||
|
double result;
|
||||||
|
|
||||||
|
int numerator = 0;
|
||||||
|
int denumerator = 0;
|
||||||
|
for (IntegerStat stat : this.integers.values())
|
||||||
|
{
|
||||||
|
numerator += stat.getCount() * stat.getValue();
|
||||||
|
denumerator += stat.getCount();
|
||||||
|
}
|
||||||
|
result = (numerator * 1. / denumerator);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the count sum.
|
||||||
|
*
|
||||||
|
* @return the count sum
|
||||||
|
*/
|
||||||
|
public int getCountSum()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
for (IntegerStat stat : this.integers.values())
|
||||||
|
{
|
||||||
|
result += stat.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxValue()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (isEmpty())
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = Integer.MIN_VALUE;
|
||||||
|
for (IntegerStat stat : this.integers.values())
|
||||||
|
{
|
||||||
|
if (stat.getValue() > result)
|
||||||
|
{
|
||||||
|
result = stat.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the min.
|
||||||
|
*
|
||||||
|
* @return the min
|
||||||
|
*/
|
||||||
|
public int getMinValue()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (isEmpty())
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = Integer.MAX_VALUE;
|
||||||
|
for (IntegerStat stat : this.integers.values())
|
||||||
|
{
|
||||||
|
if (stat.getValue() < result)
|
||||||
|
{
|
||||||
|
result = stat.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return the index of
|
||||||
|
*/
|
||||||
|
public Integer getPositionOf(final int search)
|
||||||
|
{
|
||||||
|
Integer result;
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
boolean ended = false;
|
||||||
|
result = null;
|
||||||
|
while (!ended)
|
||||||
|
{
|
||||||
|
if (index < this.board.size())
|
||||||
|
{
|
||||||
|
int value = this.board.get(index).getValue();
|
||||||
|
|
||||||
|
if (value == search)
|
||||||
|
{
|
||||||
|
result = index + 1;
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ended = true;
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if is empty.
|
||||||
|
*
|
||||||
|
* @return true, if is empty
|
||||||
|
*/
|
||||||
|
public boolean isEmpty()
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if (this.integers.size() == 0)
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator.
|
||||||
|
*
|
||||||
|
* @return the iterator
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<IntegerStat> iterator()
|
||||||
|
{
|
||||||
|
Iterator<IntegerStat> result;
|
||||||
|
|
||||||
|
update();
|
||||||
|
result = this.board.iterator();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
StringList buffer = new StringList();
|
||||||
|
for (IntegerStat stat : this.board)
|
||||||
|
{
|
||||||
|
buffer.append(String.format("%d (%d)", stat.getValue(), stat.getCount()));
|
||||||
|
}
|
||||||
|
result = buffer.toStringWithBracket();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update.
|
||||||
|
*/
|
||||||
|
public void update()
|
||||||
|
{
|
||||||
|
if (!this.isUptodate)
|
||||||
|
{
|
||||||
|
this.board.clear();
|
||||||
|
for (IntegerStat stat : this.integers.values())
|
||||||
|
{
|
||||||
|
this.board.add(stat);
|
||||||
|
}
|
||||||
|
this.board.sortByValue();
|
||||||
|
Collections.reverse(this.board);
|
||||||
|
|
||||||
|
this.isUptodate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
src/org/april/hebdobot/model/stats/IntegerStat.java
Normal file
99
src/org/april/hebdobot/model/stats/IntegerStat.java
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Stat.
|
||||||
|
*/
|
||||||
|
public class IntegerStat
|
||||||
|
{
|
||||||
|
private int value;
|
||||||
|
private int count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new distribution pair.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
*/
|
||||||
|
public IntegerStat(final int value)
|
||||||
|
{
|
||||||
|
this(value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new distribution pair.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @param count
|
||||||
|
* the count
|
||||||
|
*/
|
||||||
|
public IntegerStat(final int value, final int count)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrease count.
|
||||||
|
*/
|
||||||
|
public void dec()
|
||||||
|
{
|
||||||
|
this.count -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the count.
|
||||||
|
*
|
||||||
|
* @return the count
|
||||||
|
*/
|
||||||
|
public int getCount()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = this.count;
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value.
|
||||||
|
*
|
||||||
|
* @return the value
|
||||||
|
*/
|
||||||
|
public int getValue()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = this.value;
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments count.
|
||||||
|
*/
|
||||||
|
public void inc()
|
||||||
|
{
|
||||||
|
this.count += 1;
|
||||||
|
}
|
||||||
|
}
|
217
src/org/april/hebdobot/model/stats/IntegerStatComparator.java
Normal file
217
src/org/april/hebdobot/model/stats/IntegerStatComparator.java
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Stat.
|
||||||
|
*/
|
||||||
|
public class IntegerStatComparator implements Comparator<IntegerStat>
|
||||||
|
{
|
||||||
|
public enum Sorting
|
||||||
|
{
|
||||||
|
VALUE,
|
||||||
|
COUNT
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sorting sorting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new review data comparator.
|
||||||
|
*
|
||||||
|
* @param sorting
|
||||||
|
* the sorting
|
||||||
|
*/
|
||||||
|
public IntegerStatComparator(final Sorting sorting)
|
||||||
|
{
|
||||||
|
this.sorting = sorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compare(final IntegerStat alpha, final IntegerStat bravo)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = compare(alpha, bravo, this.sorting);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare.
|
||||||
|
*
|
||||||
|
* @param alpha
|
||||||
|
* the alpha
|
||||||
|
* @param bravo
|
||||||
|
* the bravo
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public static int compare(final Integer alpha, final Integer bravo)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
//
|
||||||
|
if ((alpha == null) && (bravo == null))
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if (alpha == null)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
else if (bravo == null)
|
||||||
|
{
|
||||||
|
result = +1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = alpha.compareTo(bravo);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare.
|
||||||
|
*
|
||||||
|
* @param alpha
|
||||||
|
* the alpha
|
||||||
|
* @param bravo
|
||||||
|
* the bravo
|
||||||
|
* @param sorting
|
||||||
|
* the sorting
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public static int compare(final IntegerStat alpha, final IntegerStat bravo, final Sorting sorting)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (sorting == null)
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (sorting)
|
||||||
|
{
|
||||||
|
case VALUE:
|
||||||
|
result = compare(getValue(alpha), getValue(bravo));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COUNT:
|
||||||
|
result = compare(getCount(alpha), getCount(bravo));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare.
|
||||||
|
*
|
||||||
|
* @param alpha
|
||||||
|
* the alpha
|
||||||
|
* @param bravo
|
||||||
|
* the bravo
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public static int compare(final Long alpha, final Long bravo)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
//
|
||||||
|
if ((alpha == null) && (bravo == null))
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if (alpha == null)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
else if (bravo == null)
|
||||||
|
{
|
||||||
|
result = +1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = alpha.compareTo(bravo);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user count.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the user count
|
||||||
|
*/
|
||||||
|
public static Integer getCount(final IntegerStat source)
|
||||||
|
{
|
||||||
|
Integer result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = source.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the duration.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the duration
|
||||||
|
*/
|
||||||
|
public static Integer getValue(final IntegerStat source)
|
||||||
|
{
|
||||||
|
Integer result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = source.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
75
src/org/april/hebdobot/model/stats/IntegerStats.java
Normal file
75
src/org/april/hebdobot/model/stats/IntegerStats.java
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2017-2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.april.hebdobot.model.stats.IntegerStatComparator.Sorting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Stats.
|
||||||
|
*/
|
||||||
|
public class IntegerStats extends ArrayList<IntegerStat>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 2632624619156256161L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new integer stats.
|
||||||
|
*/
|
||||||
|
public IntegerStats()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new integer stats.
|
||||||
|
*
|
||||||
|
* @param initialCapacity
|
||||||
|
* the initial capacity
|
||||||
|
*/
|
||||||
|
public IntegerStats(final int initialCapacity)
|
||||||
|
{
|
||||||
|
super(initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse.
|
||||||
|
*/
|
||||||
|
public void reverse()
|
||||||
|
{
|
||||||
|
Collections.reverse(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by user count.
|
||||||
|
*/
|
||||||
|
public void sortByCount()
|
||||||
|
{
|
||||||
|
Collections.sort(this, new IntegerStatComparator(Sorting.COUNT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by duration.
|
||||||
|
*/
|
||||||
|
public void sortByValue()
|
||||||
|
{
|
||||||
|
Collections.sort(this, new IntegerStatComparator(Sorting.VALUE));
|
||||||
|
}
|
||||||
|
}
|
92
src/org/april/hebdobot/model/stats/ReviewData.java
Normal file
92
src/org/april/hebdobot/model/stats/ReviewData.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2017-2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class ReviewStat.
|
||||||
|
*/
|
||||||
|
public class ReviewData
|
||||||
|
{
|
||||||
|
private LocalDateTime date;
|
||||||
|
private int userCount;
|
||||||
|
private Integer duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new stat.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* the date
|
||||||
|
* @param userCount
|
||||||
|
* the user count
|
||||||
|
* @param duration
|
||||||
|
* the duration
|
||||||
|
*/
|
||||||
|
public ReviewData(final LocalDateTime date, final int userCount, final Integer duration)
|
||||||
|
{
|
||||||
|
this.date = date;
|
||||||
|
this.userCount = userCount;
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getDate()
|
||||||
|
{
|
||||||
|
return this.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDuration()
|
||||||
|
{
|
||||||
|
return this.duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserCount()
|
||||||
|
{
|
||||||
|
return this.userCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(final LocalDateTime date)
|
||||||
|
{
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDuration(final Integer duration)
|
||||||
|
{
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserCount(final int userCount)
|
||||||
|
{
|
||||||
|
this.userCount = userCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result = String.format("%s\t%d\t%d", this.date.toString(), this.userCount, this.duration);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
273
src/org/april/hebdobot/model/stats/ReviewDataComparator.java
Normal file
273
src/org/april/hebdobot/model/stats/ReviewDataComparator.java
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2017-2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Stat.
|
||||||
|
*/
|
||||||
|
public class ReviewDataComparator implements Comparator<ReviewData>
|
||||||
|
{
|
||||||
|
public enum Sorting
|
||||||
|
{
|
||||||
|
DATE,
|
||||||
|
USERCOUNT,
|
||||||
|
DURATION
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sorting sorting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new review data comparator.
|
||||||
|
*
|
||||||
|
* @param sorting
|
||||||
|
* the sorting
|
||||||
|
*/
|
||||||
|
public ReviewDataComparator(final Sorting sorting)
|
||||||
|
{
|
||||||
|
this.sorting = sorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compare(final ReviewData alpha, final ReviewData bravo)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = compare(alpha, bravo, this.sorting);
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare.
|
||||||
|
*
|
||||||
|
* @param alpha
|
||||||
|
* the alpha
|
||||||
|
* @param bravo
|
||||||
|
* the bravo
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public static int compare(final Integer alpha, final Integer bravo)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
//
|
||||||
|
if ((alpha == null) && (bravo == null))
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if (alpha == null)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
else if (bravo == null)
|
||||||
|
{
|
||||||
|
result = +1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = alpha.compareTo(bravo);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int compare(final LocalDateTime alpha, final LocalDateTime bravo)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
//
|
||||||
|
if ((alpha == null) && (bravo == null))
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if (alpha == null)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
else if (bravo == null)
|
||||||
|
{
|
||||||
|
result = +1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = alpha.compareTo(bravo);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare.
|
||||||
|
*
|
||||||
|
* @param alpha
|
||||||
|
* the alpha
|
||||||
|
* @param bravo
|
||||||
|
* the bravo
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public static int compare(final Long alpha, final Long bravo)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
//
|
||||||
|
if ((alpha == null) && (bravo == null))
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else if (alpha == null)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
else if (bravo == null)
|
||||||
|
{
|
||||||
|
result = +1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = alpha.compareTo(bravo);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare.
|
||||||
|
*
|
||||||
|
* @param alpha
|
||||||
|
* the alpha
|
||||||
|
* @param bravo
|
||||||
|
* the bravo
|
||||||
|
* @param sorting
|
||||||
|
* the sorting
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public static int compare(final ReviewData alpha, final ReviewData bravo, final Sorting sorting)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (sorting == null)
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (sorting)
|
||||||
|
{
|
||||||
|
case DATE:
|
||||||
|
result = compare(getDate(alpha), getDate(bravo));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USERCOUNT:
|
||||||
|
result = compare(getUserCount(alpha), getUserCount(bravo));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DURATION:
|
||||||
|
result = compare(getDuration(alpha), getDuration(bravo));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the date
|
||||||
|
*/
|
||||||
|
public static LocalDateTime getDate(final ReviewData source)
|
||||||
|
{
|
||||||
|
LocalDateTime result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = source.getDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the duration.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the duration
|
||||||
|
*/
|
||||||
|
public static Integer getDuration(final ReviewData source)
|
||||||
|
{
|
||||||
|
Integer result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = source.getDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user count.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the user count
|
||||||
|
*/
|
||||||
|
public static Integer getUserCount(final ReviewData source)
|
||||||
|
{
|
||||||
|
Integer result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = source.getUserCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
186
src/org/april/hebdobot/model/stats/ReviewDatas.java
Normal file
186
src/org/april/hebdobot/model/stats/ReviewDatas.java
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2017-2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.april.hebdobot.model.stats.ReviewDataComparator.Sorting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Stats.
|
||||||
|
*/
|
||||||
|
public class ReviewDatas extends ArrayList<ReviewData>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 326880908257489774L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new ReviewDatas.
|
||||||
|
*/
|
||||||
|
public ReviewDatas()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean.
|
||||||
|
*
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
public int clean()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
Iterator<ReviewData> iterator = iterator();
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
if (iterator.next().getUserCount() < 2)
|
||||||
|
{
|
||||||
|
iterator.remove();
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last by max user count.
|
||||||
|
*
|
||||||
|
* @return the last by max user count
|
||||||
|
*/
|
||||||
|
public ReviewData getLastByMaxUserCount()
|
||||||
|
{
|
||||||
|
ReviewData result;
|
||||||
|
|
||||||
|
if (isEmpty())
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int max = Integer.MIN_VALUE;
|
||||||
|
result = null;
|
||||||
|
for (ReviewData data : this)
|
||||||
|
{
|
||||||
|
if (data.getUserCount() > max)
|
||||||
|
{
|
||||||
|
max = data.getUserCount();
|
||||||
|
result = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the max user count.
|
||||||
|
*
|
||||||
|
* @return the max user count
|
||||||
|
*/
|
||||||
|
public int getMaxUserCount()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (isEmpty())
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = Integer.MIN_VALUE;
|
||||||
|
for (ReviewData data : this)
|
||||||
|
{
|
||||||
|
if (data.getUserCount() > result)
|
||||||
|
{
|
||||||
|
result = data.getUserCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the min user count.
|
||||||
|
*
|
||||||
|
* @return the min user count
|
||||||
|
*/
|
||||||
|
public int getMinUserCount()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (isEmpty())
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = Integer.MAX_VALUE;
|
||||||
|
for (ReviewData data : this)
|
||||||
|
{
|
||||||
|
if (data.getUserCount() < result)
|
||||||
|
{
|
||||||
|
result = data.getUserCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse.
|
||||||
|
*/
|
||||||
|
public void reverse()
|
||||||
|
{
|
||||||
|
Collections.reverse(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by date.
|
||||||
|
*/
|
||||||
|
public void sortByDate()
|
||||||
|
{
|
||||||
|
Collections.sort(this, new ReviewDataComparator(Sorting.DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by duration.
|
||||||
|
*/
|
||||||
|
public void sortByDuration()
|
||||||
|
{
|
||||||
|
Collections.sort(this, new ReviewDataComparator(Sorting.DURATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by user count.
|
||||||
|
*/
|
||||||
|
public void sortByUserCount()
|
||||||
|
{
|
||||||
|
Collections.sort(this, new ReviewDataComparator(Sorting.USERCOUNT));
|
||||||
|
}
|
||||||
|
}
|
210
src/org/april/hebdobot/model/stats/ReviewDatasFile.java
Normal file
210
src/org/april/hebdobot/model/stats/ReviewDatasFile.java
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2017-2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.april.hebdobot.HebdobotException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class StatsFile.
|
||||||
|
*/
|
||||||
|
public class ReviewDatasFile
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ReviewDatasFile.class);
|
||||||
|
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new stats file.
|
||||||
|
*/
|
||||||
|
private ReviewDatasFile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append.
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* the target
|
||||||
|
* @param stat
|
||||||
|
* the stat
|
||||||
|
* @throws HebdobotException
|
||||||
|
*/
|
||||||
|
public static void append(final File file, final ReviewData stat) throws HebdobotException
|
||||||
|
{
|
||||||
|
RandomAccessFile out = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out = new RandomAccessFile(file, "rw");
|
||||||
|
out.seek(out.length());
|
||||||
|
|
||||||
|
out.writeUTF(String.format("%s\t%d\t%d\n", stat.getDate(), stat.getUserCount(), stat.getDuration()));
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException exception)
|
||||||
|
{
|
||||||
|
logger.error("File Not Found: " + exception.getMessage(), exception);
|
||||||
|
throw new HebdobotException("File Not Found appending file [" + file + "]");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (IOException exception)
|
||||||
|
{
|
||||||
|
logger.error("IO error: " + exception.getMessage(), exception);
|
||||||
|
throw new HebdobotException("IO Error appending file [" + file + "]");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtils.closeQuietly(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the stats
|
||||||
|
* @throws HebdobotException
|
||||||
|
*/
|
||||||
|
public static ReviewDatas load(final File source) throws HebdobotException
|
||||||
|
{
|
||||||
|
ReviewDatas result;
|
||||||
|
|
||||||
|
//
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
logger.error("Attempt to read null file.");
|
||||||
|
throw new IllegalArgumentException("Null parameter.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BufferedReader in = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
in = new BufferedReader(new InputStreamReader(new FileInputStream(source), DEFAULT_CHARSET_NAME));
|
||||||
|
result = read(in);
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException exception)
|
||||||
|
{
|
||||||
|
logger.error("Encoding error reading file: " + exception.getMessage(), exception);
|
||||||
|
throw new HebdobotException("Encodding error reading file [" + source + "]");
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException exception)
|
||||||
|
{
|
||||||
|
logger.error("File Not Found: " + exception.getMessage(), exception);
|
||||||
|
throw new HebdobotException("File Not Found opening file:[" + source + "]");
|
||||||
|
}
|
||||||
|
catch (IOException exception)
|
||||||
|
{
|
||||||
|
logger.error("IO error: " + exception.getMessage(), exception);
|
||||||
|
throw new HebdobotException("IO Error opening file: [" + source + "]");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IOUtils.closeQuietly(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* the source
|
||||||
|
* @return the stats
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static ReviewDatas read(final BufferedReader in) throws IOException
|
||||||
|
{
|
||||||
|
ReviewDatas result;
|
||||||
|
|
||||||
|
result = new ReviewDatas();
|
||||||
|
|
||||||
|
boolean ended = false;
|
||||||
|
while (!ended)
|
||||||
|
{
|
||||||
|
String line = in.readLine();
|
||||||
|
|
||||||
|
if (line == null)
|
||||||
|
{
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
else if ((StringUtils.isNotBlank(line)) && (!line.startsWith("#")))
|
||||||
|
{
|
||||||
|
// System.out.println("line=" + line);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
String[] tokens = line.split("[ \\s]+");
|
||||||
|
|
||||||
|
if ((tokens[0] == null) || (!tokens[0].matches("\\d{8}-\\d{2}h(\\d{2})+")))
|
||||||
|
{
|
||||||
|
logger.warn("Bad line in review stat file: [{}]", line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int year = Integer.parseInt(tokens[0].substring(0, 4));
|
||||||
|
int month = Integer.parseInt(tokens[0].substring(4, 6));
|
||||||
|
int day = Integer.parseInt(tokens[0].substring(6, 8));
|
||||||
|
int hour = Integer.parseInt(tokens[0].substring(9, 11));
|
||||||
|
int minute = Integer.parseInt(tokens[0].substring(12, 14));
|
||||||
|
LocalDateTime date = LocalDateTime.of(year, month, day, hour, minute);
|
||||||
|
|
||||||
|
int userCount = Integer.parseInt(tokens[1]);
|
||||||
|
|
||||||
|
Integer duration;
|
||||||
|
if (tokens.length == 2)
|
||||||
|
{
|
||||||
|
duration = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duration = Integer.parseInt(tokens[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReviewData stat = new ReviewData(date, userCount, duration);
|
||||||
|
|
||||||
|
result.add(stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.warn("Decode failed for line: [{}]", line, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
168
src/org/april/hebdobot/model/stats/ReviewStatsReporter.java
Normal file
168
src/org/april/hebdobot/model/stats/ReviewStatsReporter.java
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2017-2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class ReviewStatReporter.
|
||||||
|
*/
|
||||||
|
public class ReviewStatsReporter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Instantiates a new review stat reporter.
|
||||||
|
*/
|
||||||
|
private ReviewStatsReporter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Percent.
|
||||||
|
*
|
||||||
|
* @param a
|
||||||
|
* the a
|
||||||
|
* @param b
|
||||||
|
* the b
|
||||||
|
* @return the double
|
||||||
|
*/
|
||||||
|
private static double percent(final double a, final double b)
|
||||||
|
{
|
||||||
|
double result;
|
||||||
|
|
||||||
|
if (b == 0.)
|
||||||
|
{
|
||||||
|
result = 0.;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = Math.round(10000. * (a / b)) / 100.;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Percent.
|
||||||
|
*
|
||||||
|
* @param a
|
||||||
|
* the a
|
||||||
|
* @param b
|
||||||
|
* the b
|
||||||
|
* @return the double
|
||||||
|
*/
|
||||||
|
private static double percent(final int a, final int b)
|
||||||
|
{
|
||||||
|
double result;
|
||||||
|
|
||||||
|
result = percent(new Double(a).doubleValue(), new Double(b).doubleValue());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report duration.
|
||||||
|
*
|
||||||
|
* @param datas
|
||||||
|
* the datas
|
||||||
|
* @param currentDuration
|
||||||
|
* the current duration
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String reportDuration(final ReviewDatas datas, final int currentDuration)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
IntegerBoard board = new IntegerBoard();
|
||||||
|
for (ReviewData data : datas)
|
||||||
|
{
|
||||||
|
board.add(data.getDuration());
|
||||||
|
}
|
||||||
|
System.out.println("Duration board: " + board.toString());
|
||||||
|
|
||||||
|
IntegerStat stat = board.get(currentDuration);
|
||||||
|
int total = board.getCountSum();
|
||||||
|
result = String.format(
|
||||||
|
"Statistiques sur la durée de la revue (%d mn) : position %d (min=%d mn,moy=%.1f mn,max=%d mn), fréquence %d/%d (%.0f %%)",
|
||||||
|
stat.getValue(), board.getPositionOf(stat.getValue()), board.getMinValue(), board.getAverage(), board.getMaxValue(), stat.getCount(),
|
||||||
|
total, percent(stat.getCount(), total));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report new max.
|
||||||
|
*
|
||||||
|
* @param datas
|
||||||
|
* the datas
|
||||||
|
* @param currentUserCount
|
||||||
|
* the current user count
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String reportNewMaxUserCount(final ReviewDatas datas, final int currentUserCount)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
datas.sortByDate();
|
||||||
|
ReviewData last = datas.getLastByMaxUserCount();
|
||||||
|
if (currentUserCount < last.getUserCount())
|
||||||
|
{
|
||||||
|
result = "Pas de nouveau record de participation.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = "Nouveau record de participation.";
|
||||||
|
}
|
||||||
|
|
||||||
|
result = String.format("%s Dernier record %d, le %s.", result, last.getUserCount(), last.getDate().toString());
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report user count.
|
||||||
|
*
|
||||||
|
* @param datas
|
||||||
|
* the datas
|
||||||
|
* @param currentUserCount
|
||||||
|
* the current user count
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String reportUserCount(final ReviewDatas datas, final int currentUserCount)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
IntegerBoard board = new IntegerBoard();
|
||||||
|
for (ReviewData data : datas)
|
||||||
|
{
|
||||||
|
board.add(data.getUserCount());
|
||||||
|
}
|
||||||
|
System.out.println("User count board: " + board.toString());
|
||||||
|
|
||||||
|
IntegerStat stat = board.get(currentUserCount);
|
||||||
|
int total = board.getCountSum();
|
||||||
|
result = String.format("Statistiques sur le nombre de participants (%d) : position %d (min=%d,moy=%.1f,max=%d), fréquence %d/%d (%.0f %%)",
|
||||||
|
stat.getValue(), board.getPositionOf(stat.getValue()), board.getMinValue(), board.getAverage(), board.getMaxValue(), stat.getCount(),
|
||||||
|
total, percent(stat.getCount(), total));
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
169
src/org/april/hebdobot/model/stats/SimpleIntegerBoard.java
Normal file
169
src/org/april/hebdobot/model/stats/SimpleIntegerBoard.java
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2018 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.model.stats;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import fr.devinsy.util.strings.StringList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class Integers.
|
||||||
|
*/
|
||||||
|
public class SimpleIntegerBoard implements Iterable<Integer>
|
||||||
|
{
|
||||||
|
private Set<Integer> integers;
|
||||||
|
private boolean isUptodate;
|
||||||
|
private List<Integer> board;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new distribution.
|
||||||
|
*/
|
||||||
|
public SimpleIntegerBoard()
|
||||||
|
{
|
||||||
|
this.integers = new HashSet<Integer>(30);
|
||||||
|
this.isUptodate = false;
|
||||||
|
this.board = new ArrayList<Integer>(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return true, if successful
|
||||||
|
*/
|
||||||
|
public boolean add(final Integer value)
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = this.integers.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* the value
|
||||||
|
* @return the index of
|
||||||
|
*/
|
||||||
|
public Integer getPositionOf(final int search)
|
||||||
|
{
|
||||||
|
Integer result;
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
boolean ended = false;
|
||||||
|
result = null;
|
||||||
|
while (!ended)
|
||||||
|
{
|
||||||
|
if (index < this.board.size())
|
||||||
|
{
|
||||||
|
int value = this.board.get(index);
|
||||||
|
|
||||||
|
if (value == search)
|
||||||
|
{
|
||||||
|
result = index + 1;
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ended = true;
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator.
|
||||||
|
*
|
||||||
|
* @return the iterator
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<Integer> iterator()
|
||||||
|
{
|
||||||
|
Iterator<Integer> result;
|
||||||
|
|
||||||
|
update();
|
||||||
|
result = this.board.iterator();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
StringList buffer = new StringList();
|
||||||
|
for (Integer value : this.board)
|
||||||
|
{
|
||||||
|
buffer.append(value);
|
||||||
|
}
|
||||||
|
result = buffer.toStringWithBracket();
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update.
|
||||||
|
*/
|
||||||
|
public void update()
|
||||||
|
{
|
||||||
|
if (!this.isUptodate)
|
||||||
|
{
|
||||||
|
this.board.clear();
|
||||||
|
for (Integer value : this.integers)
|
||||||
|
{
|
||||||
|
this.board.add(value);
|
||||||
|
}
|
||||||
|
Collections.sort(this.board);
|
||||||
|
Collections.reverse(this.board);
|
||||||
|
|
||||||
|
this.isUptodate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
119
test/org/april/hebdobot/reviewstats/ReviewStatsTest.java
Normal file
119
test/org/april/hebdobot/reviewstats/ReviewStatsTest.java
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2011-2013,2017 Nicolas Vinot <aeris@imirhil.fr>
|
||||||
|
* Copyright (C) 2017 Christian Pierre MOMON <cmomon@april.org>
|
||||||
|
*
|
||||||
|
* This file is part of (April) Hebdobot.
|
||||||
|
*
|
||||||
|
* Hebdobot is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Hebdobot is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
package org.april.hebdobot.reviewstats;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import org.apache.log4j.BasicConfigurator;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewData;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewDatas;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewDatasFile;
|
||||||
|
import org.april.hebdobot.model.stats.ReviewStatsReporter;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Class BotMock.
|
||||||
|
*/
|
||||||
|
public class ReviewStatsTest
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ReviewStatsTest.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
BasicConfigurator.configure();
|
||||||
|
logger.info("Basic log configuration done.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test load.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* the exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testLoad() throws Exception
|
||||||
|
{
|
||||||
|
System.out.println("================");
|
||||||
|
ReviewDatas datas = ReviewDatasFile.load(new File("resources/reviewstats.csv"));
|
||||||
|
|
||||||
|
for (ReviewData data : datas)
|
||||||
|
{
|
||||||
|
System.out.println(data.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test report duration.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* the exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReportDuration() throws Exception
|
||||||
|
{
|
||||||
|
System.out.println("================");
|
||||||
|
ReviewDatas datas = ReviewDatasFile.load(new File("resources/reviewstats.csv"));
|
||||||
|
datas.clean();
|
||||||
|
System.out.println("File loaded.");
|
||||||
|
ReviewData currentReview = new ReviewData(LocalDateTime.now(), 12, 17);
|
||||||
|
datas.add(currentReview);
|
||||||
|
System.out.println(ReviewStatsReporter.reportDuration(datas, currentReview.getDuration()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test report new max user count.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* the exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReportNewMaxUserCount() throws Exception
|
||||||
|
{
|
||||||
|
System.out.println("================");
|
||||||
|
ReviewDatas datas = ReviewDatasFile.load(new File("resources/reviewstats.csv"));
|
||||||
|
datas.clean();
|
||||||
|
System.out.println("File loaded.");
|
||||||
|
ReviewData currentReview = new ReviewData(LocalDateTime.now(), 12, 17);
|
||||||
|
System.out.println(ReviewStatsReporter.reportNewMaxUserCount(datas, currentReview.getUserCount()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test report user count.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
* the exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testReportUserCount() throws Exception
|
||||||
|
{
|
||||||
|
System.out.println("================");
|
||||||
|
ReviewDatas datas = ReviewDatasFile.load(new File("resources/reviewstats.csv"));
|
||||||
|
datas.clean();
|
||||||
|
System.out.println("File loaded.");
|
||||||
|
ReviewData currentReview = new ReviewData(LocalDateTime.now(), 12, 17);
|
||||||
|
datas.add(currentReview);
|
||||||
|
System.out.println(ReviewStatsReporter.reportUserCount(datas, currentReview.getUserCount()));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user