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.Review;
|
||||
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.PastebinSettings;
|
||||
import org.april.hebdobot.pastebin.Private;
|
||||
@ -364,6 +368,36 @@ public class Hebdobot extends PircBot
|
||||
String participants = StringUtils.join(this.review.getParticipants(), " ");
|
||||
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(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