package hirondelle.predict.main.prediction;
import static hirondelle.web4j.util.Consts.FAILS;
import hirondelle.predict.main.codes.CodeTable;
import hirondelle.web4j.model.Check;
import hirondelle.web4j.model.Code;
import hirondelle.web4j.model.DateTime;
import hirondelle.web4j.model.Id;
import hirondelle.web4j.model.ModelCtorException;
import hirondelle.web4j.model.ModelUtil;
import hirondelle.web4j.security.SafeText;
import java.util.List;
public final class Prediction {
public Prediction(
Id aId, Id aParentId, SafeText aText, DateTime aCreationDate,
SafeText aRemark, Id aOutcome, DateTime aOutcomeDate
) throws ModelCtorException {
fId = aId;
fParentId = aParentId;
fText = aText;
fCreationDate = aCreationDate;
fRemark = aRemark;
fOutcome = CodeTable.codeFor(aOutcome, CodeTable.OUTCOMES);
fOutcomeDate = aOutcomeDate;
validateState(CheckDates.YES);
}
public Prediction(
Id aId, Id aParentId, SafeText aText, SafeText aRemark, Id aOutcome
) throws ModelCtorException {
fId = aId;
fParentId = aParentId;
fText = aText;
fRemark = aRemark;
fOutcome = CodeTable.codeFor(aOutcome, CodeTable.OUTCOMES);
fCreationDate = null;
fOutcomeDate = null;
validateState(CheckDates.NO);
}
public Id getId() { return fId; }
public Id getParentId() { return fParentId; }
public SafeText getText() { return fText; }
public DateTime getCreationDate() { return fCreationDate; }
public SafeText getRemark() { return fRemark; }
public Code getOutcome() { return fOutcome; }
public Integer getOutcomeScore() {
Integer result = null;
if (fOutcome != null) {
SafeText value = fOutcome.getShortText();
if( value != null ) {
result = Integer.valueOf(value.getRawString());
}
}
return result;
}
public DateTime getOutcomeDate() {
return fOutcomeDate;
}
public static Integer calculateAverageScore(List<Prediction> aPredictions){
Integer result = null;
int sum = 0;
int numScores = 0;
for(Prediction prediction : aPredictions){
if(prediction.getOutcomeScore() != null){
++numScores;
sum = sum + prediction.getOutcomeScore();
}
}
if ( numScores > 0 ) {
result = sum / numScores ; }
return result;
}
@Override public String toString(){
return ModelUtil.toStringFor(this);
}
@Override public boolean equals(Object aThat){
Boolean result = ModelUtil.quickEquals(this, aThat);
if ( result == null ) {
Prediction that = (Prediction)aThat;
result = ModelUtil.equalsFor(this.getSignificantFields(), that.getSignificantFields());
}
return result;
}
@Override public int hashCode(){
if ( fHashCode == 0 ) {
fHashCode = ModelUtil.hashCodeFor(getSignificantFields());
}
return fHashCode;
}
private final Id fId;
private final Id fParentId;
private final SafeText fText;
private final DateTime fCreationDate;
private final SafeText fRemark;
private final Code fOutcome;
private final DateTime fOutcomeDate;
private int fHashCode;
private enum CheckDates{YES, NO};
private void validateState(CheckDates aCheckDates) throws ModelCtorException {
ModelCtorException ex = new ModelCtorException();
if ( FAILS == Check.required(fParentId) ) {
ex.add("Parent Id is required. Programmer error.");
}
if ( FAILS == Check.required(fText, Check.range(1, 255)) ) {
ex.add("You must input text for your prediction (maximum 255 characters)");
}
if ( FAILS == Check.optional(fRemark, Check.range(1, 2000)) ) {
ex.add("Remark must have visible text, maximum 2,000 chars.");
}
if(CheckDates.YES == aCheckDates){
if ( FAILS == Check.required(fCreationDate) ) {
ex.add("Creation Date is missing (programmer error)");
}
if( fOutcome != null && fOutcomeDate == null) {
ex.add("Outcome and Outcome Date must appear together.");
}
if( fOutcome == null && fOutcomeDate != null) {
ex.add("Outcome and Outcome Date must appear together.");
}
}
if ( ! ex.isEmpty() ) throw ex;
}
private Object[] getSignificantFields(){
return new Object[] {fText, fCreationDate, fRemark, fOutcome, fOutcomeDate};
}
}