package net.techreadiness.plugin.datagrid;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import net.techreadiness.persistence.criteriaquery.QueryResult;
import net.techreadiness.persistence.dao.DeviceDAO;
import net.techreadiness.persistence.domain.DeviceDO;
import net.techreadiness.plugin.service.SnapshotWindowService;
import net.techreadiness.plugin.service.object.SnapshotWindow;
import net.techreadiness.plugin.service.reports.MinimumRecommendedFlag;
import net.techreadiness.plugin.service.reports.ReportsService;
import net.techreadiness.service.BaseService;
import net.techreadiness.service.ServiceContext;
import net.techreadiness.service.common.DataGrid;
import net.techreadiness.service.object.Org;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Lists;
@Component
@Scope("prototype")
@Transactional(readOnly = true)
public class DataEntryCompleteItemProviderImpl implements DataEntryCompleteItemProvider, BaseService {
private Collection<Org> orgs;
@Inject
private DeviceDAO deviceDAO;
@Inject
private ReportsService reportsService;
@Inject
private SnapshotWindowService snapshotWindowService;
private SnapshotWindow snapshot;
protected MinimumRecommendedFlag minimumRecommendedFlag;
private ServiceContext serviceContext;
@Override
public List<Map<String, String>> getPage(DataGrid<Map<String, String>> grid) {
List<Map<String, String>> orgMaps = Lists.newArrayList();
for (Org org : orgs) {
Map<String, String> map = new HashMap<>();
map.putAll(org.getAsMap());
map.putAll(org.getExtendedAttributes());
if (org.getParentOrgId() != null) {
map.put("parentOrgId", org.getParentOrgId().toString());
map.put("parentOrgName", org.getParentOrgName());
}
Collection<String> errors = new HashSet<>();
Collection<String> abnormalMessages = new ArrayList<>();
// add the error messages and the atypical data messages for displaying on the Mark Data Entry Complete page //
if (StringUtils.isBlank(org.getInternetSpeed())) {
errors.add("Estimated Internet Bandwidth");
}
if (StringUtils.isBlank(org.getInternetUtilization())) {
errors.add("Estimated Internet Bandwidth Utilization");
} else {
int internetBandwidth = 0;
internetBandwidth = Integer.parseInt(org.getInternetUtilization());
if (internetBandwidth >= 90) {
abnormalMessages.add("Internet Bandwidth utilization is greater than or equal to 90%");
} else {
if (internetBandwidth <= 5) {
abnormalMessages.add("Internet Bandwidth utilization is less than or equal to 5%");
}
}
}
if (StringUtils.isBlank(org.getNetworkSpeed())) {
errors.add("Estimated Internal Network Bandwidth");
}
if (StringUtils.isBlank(org.getNetworkUtilization())) {
errors.add("Estimated Internal Network Bandwidth Utilization");
} else {
int networkBandwidth = 0;
networkBandwidth = Integer.parseInt(org.getNetworkUtilization());
if (networkBandwidth >= 90) {
abnormalMessages.add("Internal Network Bandwidth utilization is greater than or equal to 90%");
} else {
if (networkBandwidth <= 5) {
abnormalMessages.add("Internal Network Bandwidth utilization is less than or equal to 5%");
}
}
}
if (StringUtils.isBlank(org.getTestingWindowLength())) {
errors.add("Length of Testing Window in School Days");
}
if (StringUtils.isBlank(org.getSessionsPerDay())) {
errors.add("SessionsPerDay");
} else {
int sessionsPerDay = Integer.parseInt(org.getSessionsPerDay());
if (sessionsPerDay > 4) {
abnormalMessages.add("School has 5 or more sessions per day");
}
}
int enrollmentCountTotal = getAnsweredEnrollmentCount(org);
if (enrollmentCountTotal == 0) {
errors.add("At least one grade must have a non-zero enrollment count");
}
List<DeviceDO> deviceDOs = deviceDAO.findByOrgId(org.getOrgId());
if (deviceDOs.size() == 0) {
abnormalMessages.add("School has not provided device data");
}
for (DeviceDO deviceDO : deviceDOs) {
if (deviceDO.getOperatingSystem() == null) {
errors.add("Operating System is required");
}
if (deviceDO.getMemory() == null) {
errors.add("Memory is required");
}
if (deviceDO.getScreenResolution() == null) {
errors.add("Screen Resolution is required");
}
if (deviceDO.getMonitorDisplaySize() == null) {
errors.add("Monitor / Display Size is required");
}
if (deviceDO.getEnvironment() == null) {
errors.add("Assessment Environment is required");
}
}
// we must retrieve the current snapshot in order to determine Device-to-Test-Taker Ratio > 2:1 and Enrollment
// Count per Grade > 4 standard deviations from the median enrollment//
snapshot = snapshotWindowService.getByScopeIdAndName(serviceContext, serviceContext.getScopeId(),
ReportsService.DEFAULT_SNAPSHOT_WINDOW);
QueryResult<Map<String, String>> minResult = reportsService.retrieveSummaryForOrg(
snapshot.getSnapshotWindowId(), org.getOrgId(), MinimumRecommendedFlag.MINIMUM);
Collection<Map<String, String>> results = minResult.getRows();
for (Map<String, String> snapshotMap : results) {
String studentCount = snapshotMap.get("testingStudentCount");
String totalDeviceCount = snapshotMap.get("deviceCount");
if (!(studentCount == null)
&& !(studentCount.equals("(missing)") && !(totalDeviceCount == null) && !totalDeviceCount
.equals("(missing)"))) {
int testStudentCountDoubled = NumberUtils.toInt(studentCount) * 2;
if (NumberUtils.toInt(totalDeviceCount) > testStudentCountDoubled) {
abnormalMessages.add("Device-to-test-taker ratio is greater than 2:1");
}
}
StringBuilder sbd = new StringBuilder();
sbd.append("High grade level enrollment in the following grades:");
Collection<String> highEnrollment = new HashSet<>();
if (hasHighEnrollment(org.getEnrollmentCountK(), snapshot.getCalcEnrollmentCountKMedian(),
snapshot.getCalcEnrollmentCountKStddev())) {
highEnrollment.add("K");
}
if (hasHighEnrollment(org.getEnrollmentCount1(), snapshot.getCalcEnrollmentCount1Median(),
snapshot.getCalcEnrollmentCount1Stddev())) {
highEnrollment.add("1");
}
if (hasHighEnrollment(org.getEnrollmentCount2(), snapshot.getCalcEnrollmentCount2Median(),
snapshot.getCalcEnrollmentCount2Stddev())) {
highEnrollment.add("2");
}
if (hasHighEnrollment(org.getEnrollmentCount3(), snapshot.getCalcEnrollmentCount3Median(),
snapshot.getCalcEnrollmentCount3Stddev())) {
highEnrollment.add("3");
}
if (hasHighEnrollment(org.getEnrollmentCount4(), snapshot.getCalcEnrollmentCount4Median(),
snapshot.getCalcEnrollmentCount4Stddev())) {
highEnrollment.add("4");
}
if (hasHighEnrollment(org.getEnrollmentCount5(), snapshot.getCalcEnrollmentCount5Median(),
snapshot.getCalcEnrollmentCount5Stddev())) {
highEnrollment.add("5");
}
if (hasHighEnrollment(org.getEnrollmentCount6(), snapshot.getCalcEnrollmentCount6Median(),
snapshot.getCalcEnrollmentCount6Stddev())) {
highEnrollment.add("6");
}
if (hasHighEnrollment(org.getEnrollmentCount7(), snapshot.getCalcEnrollmentCount7Median(),
snapshot.getCalcEnrollmentCount7Stddev())) {
highEnrollment.add("7");
}
if (hasHighEnrollment(org.getEnrollmentCount8(), snapshot.getCalcEnrollmentCount8Median(),
snapshot.getCalcEnrollmentCount8Stddev())) {
highEnrollment.add("8");
}
if (hasHighEnrollment(org.getEnrollmentCount9(), snapshot.getCalcEnrollmentCount9Median(),
snapshot.getCalcEnrollmentCount9Stddev())) {
highEnrollment.add("9");
}
if (hasHighEnrollment(org.getEnrollmentCount10(), snapshot.getCalcEnrollmentCount10Median(),
snapshot.getCalcEnrollmentCount10Stddev())) {
highEnrollment.add("10");
}
if (hasHighEnrollment(org.getEnrollmentCount11(), snapshot.getCalcEnrollmentCount11Median(),
snapshot.getCalcEnrollmentCount11Stddev())) {
highEnrollment.add("11");
}
if (hasHighEnrollment(org.getEnrollmentCount12(), snapshot.getCalcEnrollmentCount12Median(),
snapshot.getCalcEnrollmentCount12Stddev())) {
highEnrollment.add("12");
}
if (!highEnrollment.isEmpty()) {
for (String grade : highEnrollment) {
sbd.append(" ");
sbd.append(grade);
}
abnormalMessages.add(sbd.toString());
}
}
int count = 1;
for (String error : errors) {
map.put("error" + count, error);
}
map.put("hasErrors", String.valueOf(!errors.isEmpty()));
count = 1;
for (String abnormalMessage : abnormalMessages) {
map.put("Atypical" + count, abnormalMessage);
}
map.put("hasAtypicalData", String.valueOf(!abnormalMessages.isEmpty()));
map.put("orgTypeId", org.getOrgTypeId().toString());
map.put("orgTypeName", org.getOrgTypeName());
map.put("hasDevices", String.valueOf(org.isOrgTypeAllowDevice()));
orgMaps.add(map);
}
return orgMaps;
}
private static boolean hasHighEnrollment(String enrollment, Integer median, Double stdDev) {
if (enrollment != null && !"(missing)".equals(enrollment) && median != null && stdDev != null) {
int count = NumberUtils.toInt(enrollment);
if (count > median.intValue() + stdDev.doubleValue() * 4) {
return true;
}
}
return false;
}
@Override
public void setServiceContext(ServiceContext serviceContext) {
this.serviceContext = serviceContext;
}
@Override
public int getTotalNumberOfItems(DataGrid<Map<String, String>> grid) {
return orgs.size();
}
@Override
public void setOrgs(Collection<Org> orgs) {
this.orgs = orgs;
}
private static int getAnsweredEnrollmentCount(Org org) {
int count = (StringUtils.isBlank(org.getEnrollmentCountK()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount1()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount2()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount3()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount4()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount5()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount6()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount7()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount8()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount9()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount10()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount11()) ? 0 : 1)
+ (StringUtils.isBlank(org.getEnrollmentCount12()) ? 0 : 1);
return count;
}
public void setSnapshotWindow(SnapshotWindow snapshotWindow) {
snapshot = snapshotWindow;
}
}