派生自 projectDept/qhighschool

yn147
2023-11-24 26780c533f2c2af6b9216306f649c1bcede94e4a
src/main/java/com/qxueyou/scc/teach/subject/service/impl/SubjectService.java
@@ -2,14 +2,12 @@
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import com.qxueyou.scc.base.model.UserInfoWrapper;
import com.qxueyou.scc.sys.model.CacheParamters;
import com.qxueyou.scc.teach.subject.model.view.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@@ -61,1488 +59,1610 @@
import com.qxueyou.scc.teach.subject.model.Subject;
import com.qxueyou.scc.teach.subject.model.SubjectChapter;
import com.qxueyou.scc.teach.subject.model.SubjectLecture;
import com.qxueyou.scc.teach.subject.model.view.MySubjectV;
import com.qxueyou.scc.teach.subject.model.view.OpenSubjectV;
import com.qxueyou.scc.teach.subject.model.view.QMyLectureV;
import com.qxueyou.scc.teach.subject.model.view.QMySubjectV;
import com.qxueyou.scc.teach.subject.model.view.QOpenSubjectV;
import com.qxueyou.scc.teach.subject.service.ILectureService;
import com.qxueyou.scc.teach.subject.service.ISubjectService;
import com.qxueyou.scc.user.model.QUser;
import com.qxueyou.scc.user.model.UserTeacher;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
@Service
public class SubjectService extends CommonAppService implements ISubjectService {
   private final Logger log = LogManager.getLogger(SubjectService.class);
    private final Logger log = LogManager.getLogger(SubjectService.class);
   @Autowired
   SubjectDAO subjectDAO;
    @Autowired
    SubjectDAO subjectDAO;
   @Autowired
   IFileService fileService;
    @Autowired
    IFileService fileService;
   @Autowired
   ILectureService lectureService;
   @Autowired
   IClassLectureService clsLectureService;
    @Autowired
    ILectureService lectureService;
   @Autowired
   IProgressService progressService;
    @Autowired
    IClassLectureService clsLectureService;
   @Autowired
   IExamService examService;
    @Autowired
    IProgressService progressService;
   @Autowired
   IExerciseInfoService exerciseInfoService;
    @Autowired
    IExamService examService;
   @Autowired
   ProgressDAO progressDao;
    @Autowired
    IExerciseInfoService exerciseInfoService;
   @Autowired
   private ITeacherService teacherService;
   @Autowired
   private IMediaLiveService mediaLiveService;
    @Autowired
    ProgressDAO progressDao;
   @Override
   public Result add(String subjectName,String coverPageFileId, String contentFileId,int type) {
    @Autowired
    private ITeacherService teacherService;
      Subject subject = new Subject();
      if (StringUtils.isNotEmpty(coverPageFileId)) {
         ResFile file = fileService.read(coverPageFileId);
         subject.setCoverPageFileId(coverPageFileId);
         subject.setCoverPageUrl(file.getPath());
      }
    @Autowired
    private IMediaLiveService mediaLiveService;
      TraceUtils.setCreateTrace(subject);
      subject.setContentFileId(contentFileId);
      subject.setName(subjectName);
      subject.setStatus(Subject.STATUS_DRAFT);
      subject.setLectureCount(0);
      subject.setType(type);
      subject.setOrgId(ClientUtils.getOrgId());
      save(subject);
      //初始化创建 根节点
      SubjectChapter chapter = new SubjectChapter();
      TraceUtils.setCreateTrace(chapter);
      chapter.setName("根节点");
      chapter.setSubjectId(subject.getSubjectId());
      chapter.setParentChapterId(SubjectChapter.ROOT_CHAPTER_ID);
      save(chapter);
    @Override
    public Result add(String subjectName, String coverPageFileId, String contentFileId, int type, Date startTime, Date endTime) {
      return new Result(true,"success",CollectionUtils.newObjectMap("subjectId",subject.getSubjectId()));
   }
        Subject subject = new Subject();
        if (StringUtils.isNotEmpty(coverPageFileId)) {
            ResFile file = fileService.read(coverPageFileId);
            subject.setCoverPageFileId(coverPageFileId);
            subject.setCoverPageUrl(file.getPath());
        }
   @Override
   public Result update(String subjectId, String subjectName, String coverPageFileId, String contentFileId,int type) {
      Subject subject = read(Subject.class, subjectId);
      if (StringUtils.isNotEmpty(coverPageFileId)) {
         ResFile file = fileService.read(coverPageFileId);
         subject.setCoverPageUrl(file.getPath());
         subject.setCoverPageFileId(coverPageFileId);
      }else{
         subject.setCoverPageUrl(null);
         subject.setCoverPageFileId(null);
      }
        TraceUtils.setCreateTrace(subject);
        subject.setContentFileId(contentFileId);
        subject.setName(subjectName);
        subject.setStatus(Subject.STATUS_DRAFT);
        subject.setLectureCount(0);
        subject.setType(type);
        //签到时间
        subject.setStartTime(startTime);
        subject.setEndTime(endTime);
        subject.setOrgId(ClientUtils.getOrgId());
      TraceUtils.setUpdateTrace(subject);
      subject.setContentFileId(contentFileId);
      subject.setName(subjectName);
      subject.setType(type);
        save(subject);
      save(subject);
      //更新所有关联的课程
      if(subject.getType()==Subject.TYPE_ORG_SUBJECT){
         this.bulkUpdate("update Subject t set t.name=?,t.contentFileId=?,"
               + "t.coverPageFileId=?,t.coverPageUrl=? where t.deleteFlag is false and t.origSubjectId=? ",new Object[]{subject.getName(),
                     subject.getContentFileId(),subject.getCoverPageFileId(),subject.getCoverPageUrl(),subject.getSubjectId()} );
      }
      return new Result(true, "success");
   }
        //初始化创建 根节点
        SubjectChapter chapter = new SubjectChapter();
        TraceUtils.setCreateTrace(chapter);
        chapter.setName("根节点");
        chapter.setSubjectId(subject.getSubjectId());
        chapter.setParentChapterId(SubjectChapter.ROOT_CHAPTER_ID);
        save(chapter);
   @Override
   public Result delete(String[] subjectIds) {
      for (String subjectId : subjectIds) {
         deleteSubject(subjectId);
         //删除班级课程
         List<Map<String,Object>> result = this.findListWithMapByHql(
               "select r.classId as classId,r.subjectId as subjectId from ClsClassReSubject r,Subject j  "
               + "where r.subjectId = j.subjectId and j.origSubjectId=:origSubjectId and r.deleteFlag is false and j.deleteFlag is false",
               CollectionUtils.newObjectMap("origSubjectId",subjectId));
         if(result!=null && result.size()>0){
            for(Map<String,Object> map : result){
               this.deleteClsSubject((String)map.get("classId"), new String []{(String)map.get("subjectId")});
            }
         }
      }
        return new Result(true, "success", CollectionUtils.newObjectMap("subjectId", subject.getSubjectId()));
    }
      return new Result(true, "success");
   }
    @Override
    public Result update(String subjectId, String subjectName, String coverPageFileId, String contentFileId, int type) {
        Subject subject = read(Subject.class, subjectId);
        if (StringUtils.isNotEmpty(coverPageFileId)) {
            ResFile file = fileService.read(coverPageFileId);
            subject.setCoverPageUrl(file.getPath());
            subject.setCoverPageFileId(coverPageFileId);
        } else {
            subject.setCoverPageUrl(null);
            subject.setCoverPageFileId(null);
        }
   /**
    * 删除单个课程
    *
    * @param chapterId
    *            章节id
    * @return
    */
   private Result deleteSubject(String subjectId) {
        TraceUtils.setUpdateTrace(subject);
        subject.setContentFileId(contentFileId);
        subject.setName(subjectName);
        subject.setType(type);
      Subject subject = read(Subject.class, subjectId);
        save(subject);
      TraceUtils.setUpdateTrace(subject);
      subject.setDeleteFlag(true);
        //更新所有关联的课程
        if (subject.getType() == Subject.TYPE_ORG_SUBJECT) {
            this.bulkUpdate("update Subject t set t.name=?,t.contentFileId=?,"
                    + "t.coverPageFileId=?,t.coverPageUrl=? where t.deleteFlag is false and t.origSubjectId=? ", new Object[]{subject.getName(),
                    subject.getContentFileId(), subject.getCoverPageFileId(), subject.getCoverPageUrl(), subject.getSubjectId()});
        }
      save(subject);
        return new Result(true, "success");
    }
      return new Result(true, "success");
   }
    @Override
    public Result delete(String[] subjectIds) {
        for (String subjectId : subjectIds) {
            deleteSubject(subjectId);
   @Override
   public List<Subject> list(String text, String teacherId, String status,Integer type, Integer pageSize, Integer pageNum) {
            //删除班级课程
            List<Map<String, Object>> result = this.findListWithMapByHql(
                    "select r.classId as classId,r.subjectId as subjectId from ClsClassReSubject r,Subject j  "
                            + "where r.subjectId = j.subjectId and j.origSubjectId=:origSubjectId and r.deleteFlag is false and j.deleteFlag is false",
                    CollectionUtils.newObjectMap("origSubjectId", subjectId));
      StringBuffer hql = new StringBuffer("from Subject where name like ? and orgId=? and deleteFlag is false and origSubjectId is null ");
            if (result != null && result.size() > 0) {
                for (Map<String, Object> map : result) {
                    this.deleteClsSubject((String) map.get("classId"), new String[]{(String) map.get("subjectId")});
                }
            }
        }
      List<Object> args = CollectionUtils.newList(text + "%",ClientUtils.getOrgId());
        return new Result(true, "success");
    }
      if(type!=null){
         hql.append(" and type=?");
         args.add(type);
      }
      if (!StringUtils.isEmpty(status)) {
         hql.append(" and status=?");
         args.add(status);
      }
    /**
     * 删除单个课程
     *
     * @param chapterId 章节id
     * @return
     */
    private Result deleteSubject(String subjectId) {
        Subject subject = read(Subject.class, subjectId);
        TraceUtils.setUpdateTrace(subject);
        subject.setDeleteFlag(true);
        save(subject);
        return new Result(true, "success");
    }
    @Override
    public List<Subject> list(String text, String teacherId, String status, Integer type, Integer pageSize, Integer pageNum) {
        //and origSubjectId is null
        StringBuffer hql = new StringBuffer("from Subject where name like ? and orgId=? and deleteFlag is false  ");
        List<Object> args = CollectionUtils.newList(text + "%", ClientUtils.getOrgId());
        if (type != null) {
            hql.append(" and type=?");
            args.add(type);
        }
        if (!StringUtils.isEmpty(status)) {
            hql.append(" and status=?");
            args.add(status);
        }
//        if (!StringUtils.isEmpty(teacherId)) {
//            hql.append(" and createId=?");
//            args.add(teacherId);
//        }
        if (!StringUtils.isEmpty(teacherId)) {
            hql.append(" and teacherId=?");
            args.add(teacherId);
        }
        hql.append(" order by createTime desc");
        List<Subject> result = findList(hql.toString(), new Pager(pageSize, pageNum), args, Subject.class);
        return result;
    }
    /**
     * app教师端课程列表
     *
     * @param text
     * @param status
     * @param type
     * @param pageSize
     * @param pageNum
     * @return
     */
    @Override
    public Result teacherSubjectList(Pager pager, String keyword, String status, Integer type) {
        String teacherId = teacherService.getTeacherIdByUserId(ClientUtils.getUserId());
        if (StringUtils.isEmpty(teacherId)) {
            return new Result(false, "当前用户无老师角色");
        }
        QSubject qSubject = QSubject.subject;
        QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
        QProgress qProgress = QProgress.progress;
        QClsClassReSubject qClsClassReSubject = QClsClassReSubject.clsClassReSubject;
        JPAQuery<Tuple> query = this.getQueryFactory()
                .select(qSubject.subjectId, qSubject.name, qSubject.term, qSubject.coverPageUrl, qSubject.schoolYear, qSubject.createTime, qSubject.type)
                .from(qSubject)
                .where(qSubject.deleteFlag.isFalse()
                        .and(qSubject.status.eq(Subject.STATUS_ISSUED)).and(qSubject.type.eq(type))
                        .and(qSubject.createId.eq(ClientUtils.getUserId()))
                        .and(qSubject.name.like("%" + keyword + "%")));
        long count = query.fetchCount();
        List<Map<String, Object>> listData = query.orderBy(qSubject.createTime.desc()).limit(pager.getPageSize())
                .offset(pager.getOffset()).fetch().stream().map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(10);
                    String subjectId = tuple.get(qSubject.subjectId);
                    map.put("name", tuple.get(qSubject.name));
                    map.put("subjectId", subjectId);
                    map.put("schoolYear", tuple.get(qSubject.schoolYear));
                    map.put("term", tuple.get(qSubject.term));
                    map.put("coverPageUrl", tuple.get(qSubject.coverPageUrl));
                    map.put("createTime", tuple.get(qSubject.createTime));
                    map.put("type", tuple.get(qSubject.type));
                    map.put("classId", "");
                    map.put("studyCount", this.getQueryFactory().selectDistinct(qProgress.learnerId).from(qProgress, qSubjectLecture)
                            .where(qProgress.deleteFlag.isFalse().and(qSubjectLecture.subjectId.eq(subjectId)).and(qProgress.targetType.eq(Progress.PROGRESS_TYPE_LECTURE))
                                    .and(qProgress.targetId.eq(qSubjectLecture.lectureId)).and(qSubjectLecture.deleteFlag.isFalse())).fetchCount());
                    map.put("classCount",
                            this.getQueryFactory().selectDistinct(qClsClassReSubject.classId)
                                    .from(qClsClassReSubject, qSubject)
                                    .where(qSubject.deleteFlag.isFalse().and(qClsClassReSubject.deleteFlag.isFalse())
                                            .and(qClsClassReSubject.subjectId.eq(qSubject.subjectId)).and(qSubject.origSubjectId.eq(subjectId))).fetchCount());
                    return map;
                }).collect(Collectors.toList());
        return new Result(true, "", CollectionUtils.newObjectMap("count", count, "listData", listData));
    }
    @Override
    public int listCount(String text, String teacherId, String status, Integer type) {
        StringBuffer hql = new StringBuffer("from Subject where name like ? and orgId=? and deleteFlag is false and origSubjectId is null ");
        List<Object> args = CollectionUtils.newList(text + "%", ClientUtils.getOrgId());
        if (type != null) {
            hql.append(" and type=?");
            args.add(type);
        }
        if (StringUtils.isNotBlank(status)) {
            hql = hql.append(" and status = ?");
            args.add(status);
        }
        if (!StringUtils.isEmpty(teacherId)) {
            hql.append(" and createId=?");
            args.add(teacherId);
        }
        return findCount(hql.toString(), args);
    }
    @Override
    public Subject read(String subjectId) {
        return read(Subject.class, subjectId);
    }
    @Override
    public String readSubjectContent(String subjectId) {
        Subject sub = read(subjectId);
        //读取原课程
        if (StringUtils.isNotBlank(sub.getOrigSubjectId())) {
            sub = read(sub.getOrigSubjectId());
        }
        try {
            if (!StringUtils.isEmpty(sub.getContentFileId())) {
                return IOUtils.toString(fileService.readStreamById(sub.getContentFileId()));
            }
        } catch (Exception e) {
            log.error(e, e);
        }
        return null;
    }
      if (!StringUtils.isEmpty(teacherId)) {
         hql.append(" and createId=?");
         args.add(teacherId);
      }
      hql.append(" order by createTime desc");
      List<Subject> result = findList(hql.toString(), new Pager(pageSize, pageNum), args, Subject.class);
      return result;
   }
    @Override
    public Result doRelease(String[] subjectIds) {
        for (String subjectId : subjectIds) {
            releaseSubject(subjectId);
        }
   /**
    * app教师端课程列表
    *
    * @param text
    * @param status
    * @param type
    * @param pageSize
    * @param pageNum
    * @return
    */
   @Override
   public Result teacherSubjectList(Pager pager, String keyword, String status,Integer type) {
      String teacherId = teacherService.getTeacherIdByUserId(ClientUtils.getUserId());
      if(StringUtils.isEmpty(teacherId)) {
         return new Result(false, "当前用户无老师角色");
      }
      QSubject qSubject = QSubject.subject;
      QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
      QProgress qProgress = QProgress.progress;
      QClsClassReSubject qClsClassReSubject = QClsClassReSubject.clsClassReSubject;
      JPAQuery<Tuple> query = this.getQueryFactory()
            .select(qSubject.subjectId, qSubject.name, qSubject.term,qSubject.coverPageUrl, qSubject.schoolYear, qSubject.createTime, qSubject.type)
            .from(qSubject)
            .where(qSubject.deleteFlag.isFalse()
                  .and(qSubject.status.eq(Subject.STATUS_ISSUED)).and(qSubject.type.eq(type))
                  .and(qSubject.createId.eq(ClientUtils.getUserId()))
                  .and(qSubject.name.like("%" + keyword + "%")));
      long count = query.fetchCount();
      List<Map<String, Object>> listData = query.orderBy(qSubject.createTime.desc()).limit(pager.getPageSize())
            .offset(pager.getOffset()).fetch().stream().map(tuple -> {
               Map<String, Object> map = new HashMap<String, Object>(10);
               String subjectId = tuple.get(qSubject.subjectId);
        return new Result(true, "success");
    }
               map.put("name", tuple.get(qSubject.name));
               map.put("subjectId", subjectId);
               map.put("schoolYear", tuple.get(qSubject.schoolYear));
               map.put("term", tuple.get(qSubject.term));
               map.put("coverPageUrl", tuple.get(qSubject.coverPageUrl));
               map.put("createTime", tuple.get(qSubject.createTime));
               map.put("type", tuple.get(qSubject.type));
               map.put("classId", "");
               map.put("studyCount", this.getQueryFactory().selectDistinct(qProgress.learnerId).from(qProgress, qSubjectLecture)
                     .where(qProgress.deleteFlag.isFalse().and(qSubjectLecture.subjectId.eq(subjectId)).and(qProgress.targetType.eq(Progress.PROGRESS_TYPE_LECTURE))
                           .and(qProgress.targetId.eq(qSubjectLecture.lectureId)).and(qSubjectLecture.deleteFlag.isFalse())).fetchCount());
               map.put("classCount",
                     this.getQueryFactory().selectDistinct(qClsClassReSubject.classId)
                           .from(qClsClassReSubject, qSubject)
                           .where(qSubject.deleteFlag.isFalse().and(qClsClassReSubject.deleteFlag.isFalse())
                                 .and(qClsClassReSubject.subjectId.eq(qSubject.subjectId)).and(qSubject.origSubjectId.eq(subjectId))).fetchCount());
    @Override
    public Result doCancel(String[] subjectIds) {
        for (String subjectId : subjectIds) {
            cancelSubject(subjectId);
        }
               return map;
            }).collect(Collectors.toList());
      return new Result(true, "", CollectionUtils.newObjectMap("count", count, "listData", listData));
   }
        return new Result(true, "success");
    }
   @Override
   public int listCount(String text, String teacherId, String status,Integer type) {
      StringBuffer hql = new StringBuffer("from Subject where name like ? and orgId=? and deleteFlag is false and origSubjectId is null ");
      List<Object> args = CollectionUtils.newList(text + "%",ClientUtils.getOrgId());
      if(type!=null){
         hql.append(" and type=?");
         args.add(type);
      }
      if (StringUtils.isNotBlank(status)) {
         hql = hql.append(" and status = ?");
         args.add(status);
      }
    /**
     * 发布单个课程
     *
     * @param chapterId 章节id
     * @return
     */
    private Result releaseSubject(String subjectId) {
      if (!StringUtils.isEmpty(teacherId)) {
         hql.append(" and createId=?");
         args.add(teacherId);
      }
        Subject subject = read(Subject.class, subjectId);
      return findCount(hql.toString(), args);
        TraceUtils.setUpdateTrace(subject);
        subject.setStatus(Subject.STATUS_ISSUED);
   }
        save(subject);
   @Override
   public Subject read(String subjectId) {
      return read(Subject.class, subjectId);
   }
        //更新所有关联的课程
        this.bulkUpdate("update Subject set status='" + Subject.STATUS_ISSUED + "' where origSubjectId=? and deleteFlag is false ", new Object[]{subjectId});
   @Override
   public String readSubjectContent(String subjectId) {
        return new Result(true, "success");
    }
      Subject sub = read(subjectId);
      //读取原课程
      if(StringUtils.isNotBlank(sub.getOrigSubjectId())) {
         sub = read(sub.getOrigSubjectId());
      }
    /**
     * 发布单个课程
     *
     * @param chapterId 章节id
     * @return
     */
    private Result cancelSubject(String subjectId) {
      try {
         if(!StringUtils.isEmpty(sub.getContentFileId())){
            return IOUtils.toString(fileService.readStreamById(sub.getContentFileId()));
         }
      } catch (Exception e) {
         log.error(e, e);
      }
      return null;
        Subject subject = read(Subject.class, subjectId);
   }
        TraceUtils.setUpdateTrace(subject);
        subject.setStatus(Subject.STATUS_OFFLINE);
   @Override
   public Result doRelease(String[] subjectIds) {
      for (String subjectId : subjectIds) {
         releaseSubject(subjectId);
      }
        save(subject);
      return new Result(true, "success");
   }
        //更新所有关联的课程
        this.bulkUpdate("update Subject set status='" + Subject.STATUS_OFFLINE + "' where origSubjectId=? and deleteFlag is false ", new Object[]{subjectId});
   @Override
   public Result doCancel(String[] subjectIds) {
      for (String subjectId : subjectIds) {
         cancelSubject(subjectId);
      }
        return new Result(true, "success");
    }
      return new Result(true, "success");
   }
    @Override
    public List<MySubjectV> listMySubjectV(String classId, String userId) {
        StringBuffer hql = new StringBuffer("from MySubjectV p where p.id.userId=? and p.subjectStatus=?");
        List<Object> args = CollectionUtils.newList(userId, Subject.STATUS_ISSUED);
   /**
    * 发布单个课程
    *
    * @param chapterId
    *            章节id
    * @return
    */
   private Result releaseSubject(String subjectId) {
        if (!StringUtils.isEmpty(classId)) {
            hql.append(" and p.id.classId = ?");
            args.add(classId);
      Subject subject = read(Subject.class, subjectId);
        }
        List<MySubjectV> result = find(hql.toString(), args, MySubjectV.class);
      TraceUtils.setUpdateTrace(subject);
      subject.setStatus(Subject.STATUS_ISSUED);
        return result;
    }
      save(subject);
      //更新所有关联的课程
      this.bulkUpdate("update Subject set status='" + Subject.STATUS_ISSUED + "' where origSubjectId=? and deleteFlag is false ",new Object[]{subjectId});
      return new Result(true, "success");
   }
    @Override
    public List<OpenSubjectV> listOpenSubjectV() {
        StringBuffer hql = new StringBuffer("from OpenSubjectV p where 1 = ?");
        int param = 1;
        List<Object> args = CollectionUtils.newList(param);
   /**
    * 发布单个课程
    *
    * @param chapterId
    *            章节id
    * @return
    */
   private Result cancelSubject(String subjectId) {
      Subject subject = read(Subject.class, subjectId);
        List<OpenSubjectV> result = find(hql.toString(), args, OpenSubjectV.class);
      TraceUtils.setUpdateTrace(subject);
      subject.setStatus(Subject.STATUS_OFFLINE);
        return result;
    }
      save(subject);
      //更新所有关联的课程
      this.bulkUpdate("update Subject set status='" + Subject.STATUS_OFFLINE + "' where origSubjectId=? and deleteFlag is false ",new Object[]{subjectId});
      return new Result(true, "success");
   }
    @Override
    public List<Map<String, Object>> listChapterStudyProgress(String subjectId) {
   @Override
   public List<MySubjectV> listMySubjectV(String classId,String userId) {
      StringBuffer hql = new StringBuffer("from MySubjectV p where p.id.userId=? and p.subjectStatus=?");
//      UserInfoWrapper wrapper=new UserInfoWrapper();
//      System.out.println("cc"+ClientUtils.getUserInfo().getInfo(wrapper.INF_CLASS_ID));
//      System.out.println("1-"+ClientUtils.getUserId()+"2-"+Subject.STATUS_ISSUED+"aaaaaa"+userId);
      List<Object> args = CollectionUtils.newList(userId,Subject.STATUS_ISSUED);
        QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
        List<Map<String, Object>> lstResult = this.getQueryFactory().selectFrom(qSubjectProgressTreeV).
                where(qSubjectProgressTreeV.id.nodeId.eq(subjectId).and(qSubjectProgressTreeV.id.userId.eq(ClientUtils.getUserId())))
                .fetch().stream().map(objSubjectProgressTreeV -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("chapterName", objSubjectProgressTreeV.getNodeName());
                    map.put("chapterId", objSubjectProgressTreeV.getId().getNodeId());
                    map.put("percent", objSubjectProgressTreeV.getPercent());
                    map.put("studyTime", objSubjectProgressTreeV.getProgressValue());
      if (!StringUtils.isEmpty(classId)) {
         hql.append(" and p.id.classId = ?");
         args.add(classId);
                    return map;
                }).collect(Collectors.toList());
      }
      List<MySubjectV> result = find(hql.toString(), args, MySubjectV.class);
        return lstResult;
    }
      return result;
   }
    @Override
    public MySubjectV getMy1stSubjectVById(String subjectId) {
        String hql = "from MySubjectV p where p.id.userId=? and p.id.subjectId=?";
        String UserId = ClientUtils.getUserId();
        MySubjectV result = findUnique(hql, CollectionUtils.newList(UserId, subjectId),
                MySubjectV.class);
        return result;
    }
   @Override
   public List<Map<String, Object>> listChapterStudyProgress(String subjectId) {
    @Override
    public Result addLectureCount(String subjectId, int count) {
      QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
       List<Map<String, Object>> lstResult = this.getQueryFactory().selectFrom(qSubjectProgressTreeV).
             where(qSubjectProgressTreeV.parentId.eq(subjectId).and(qSubjectProgressTreeV.id.userId.eq(ClientUtils.getUserId())))
             .fetch().stream().map(objSubjectProgressTreeV ->{
                Map<String, Object> map = new HashMap<>();
                map.put("chapterName", objSubjectProgressTreeV.getNodeName());
                map.put("chapterId", objSubjectProgressTreeV.getId().getNodeId());
                map.put("percent", objSubjectProgressTreeV.getPercent());
                map.put("studyTime", objSubjectProgressTreeV.getProgressValue());
                return map;
             }).collect(Collectors.toList());
      return lstResult;
   }
        subjectDAO.addLectureCount(subjectId, count);
   @Override
   public MySubjectV getMy1stSubjectVById(String subjectId) {
      String hql = "from MySubjectV p where p.id.userId=? and p.id.subjectId=?";
        return new Result(true);
    }
      MySubjectV result = findUnique(hql, CollectionUtils.newList(ClientUtils.getUserId(), subjectId),
            MySubjectV.class);
    @Override
    public Subject readSubject(String subjectId) {
      return result;
   }
        return read(Subject.class, subjectId);
    }
   @Override
   public Result addLectureCount(String subjectId, int count) {
    @Override
    public Result addClsSubject(String classId, String origSubjectId, String teacherId, Integer schoolYear, Integer term) throws IllegalAccessException, InvocationTargetException {
        //新增老师课程
//        Subject newSubject = new Subject();
        Subject newSubject = this.read(origSubjectId);
        UserTeacher teacher = this.read(UserTeacher.class, teacherId);
//        BeanUtils.copyProperties(newSubject, origSubject);
      subjectDAO.addLectureCount(subjectId, count);
        TraceUtils.setCreateTrace(newSubject);
//        newSubject.setSubjectId(null);
        newSubject.setTeacherId(teacherId);
        newSubject.setSchoolYear(schoolYear);
        newSubject.setTerm(term);
//        newSubject.setStatus(origSubject.getStatus());
        newSubject.setOrigSubjectId(origSubjectId);
        newSubject.setOrigCopySubjectId(origSubjectId);
//        newSubject.setType(Subject.TYPE_CLS_SUBJECT);
        newSubject.setType(Subject.TYPE_ORG_SUBJECT);
        newSubject.setTeacherName(teacher.getName());
        newSubject.setOrgId(ClientUtils.getOrgId());
        save(newSubject);
      return new Result(true);
   }
        //添加班级课程关系
        addClassReSubject(newSubject.getSubjectId(), classId);
   @Override
   public Subject readSubject(String subjectId) {
        //复制课件
        clsLectureService.doCopyLecturesToClass(origSubjectId, newSubject.getSubjectId(), classId);
      return read(Subject.class, subjectId);
   }
        return new Result(true, "success", CollectionUtils.newStringMap("subjectId", newSubject.getSubjectId()));
    }
   @Override
   public Result addClsSubject(String classId,String origSubjectId, String teacherId, Integer schoolYear,Integer term) throws IllegalAccessException, InvocationTargetException {
      //新增老师课程
      Subject newSubject = new Subject();
      Subject origSubject = this.read(origSubjectId);
      UserTeacher teacher = this.read(UserTeacher.class, teacherId);
      BeanUtils.copyProperties(newSubject,origSubject);
      TraceUtils.setCreateTrace(newSubject);
      newSubject.setSubjectId(null);
      newSubject.setTeacherId(teacherId);
      newSubject.setSchoolYear(schoolYear);
      newSubject.setTerm(term);
      newSubject.setStatus(origSubject.getStatus());
      newSubject.setOrigSubjectId(origSubjectId);
      newSubject.setOrigCopySubjectId(origSubjectId);
      newSubject.setType(Subject.TYPE_CLS_SUBJECT);
      newSubject.setTeacherName(teacher.getName());
      newSubject.setOrgId(ClientUtils.getOrgId());
      save(newSubject);
      //添加班级课程关系
      addClassReSubject(newSubject.getSubjectId(),classId);
      //复制课件
      clsLectureService.doCopyLecturesToClass(origSubjectId,newSubject.getSubjectId(),classId);
      return new Result(true, "success",CollectionUtils.newStringMap("subjectId",newSubject.getSubjectId()));
   }
    private void addClassReSubject(String subjectId, String classId) {
        ClsClassReSubject re = new ClsClassReSubject();
        TraceUtils.setCreateTrace(re);
        re.setClassId(classId);
        re.setSubjectId(subjectId);
        save(re);
    }
   @Override
   public Result updateClsSubject(String classId,String subjectId,String origSubjectId, String teacherId, Integer schoolYear,Integer term) {
      Subject origSubject = this.read(origSubjectId);
      Subject subject = this.read(subjectId);
      UserTeacher teacher = this.read(UserTeacher.class, teacherId);
      //如果原课程做出了修改
      if(!origSubjectId.equals(subject.getOrigSubjectId())){
         subject.setContentFileId(origSubject.getCoverPageFileId());
         subject.setCoverPageUrl(origSubject.getCoverPageUrl());
         subject.setContentFileId(origSubject.getContentFileId());
         subject.setName(origSubject.getName());
         subject.setOrigSubjectId(origSubjectId);
         subject.setOrigCopySubjectId(origSubjectId);
         //清理并复制原课程
         clsLectureService.doClearLecturesToClass(classId,subjectId);
         clsLectureService.doCopyLecturesToClass(origSubjectId, subjectId, classId);
      }
      TraceUtils.setUpdateTrace(subject);
      subject.setTeacherId(teacherId);
      subject.setTeacherName(teacher.getName());
      subject.setSchoolYear(schoolYear);
      subject.setTerm(term);
      save(subject);
      return new Result(true, "success");
   }
   @Override
   public Result deleteClsSubject(String classId,String[] subjectIds) {
      Map<String,Object> paramMap = new HashMap<String,Object>();
      paramMap.put("classId", classId);
      paramMap.put("subjectIds", subjectIds);
      List<String>  reIdLst =  this.findByComplexHql("select r.clsReSubjectId from ClsClassReSubject r where r.deleteFlag is false and r.classId=:classId and r.subjectId in (:subjectIds) ",
               paramMap, String.class);
      //删除关联关系
      if(reIdLst!=null && reIdLst.size()>0){
         this.bulkUpdateInLoop("update ClsClassReSubject set deleteFlag = true where clsReSubjectId=?", reIdLst.toArray());
      }
      this.delete(subjectIds);
      return new Result(true, "success");
   }
   @Override
   public Result getPerformance4Subject() {
      String findCompleteCountByHql = "from MySubjectV where id.userId = ? and percent = 1 ";
      String findUndoneByHql = "from MySubjectV where id.userId = ? and (percent != 1 or percent is null)";
      String userId = ClientUtils.getUserId();
      int CompleteCount = findCount(findCompleteCountByHql, CollectionUtils.newList(userId));
      int UndoneCount = findCount(findUndoneByHql, CollectionUtils.newList(userId));
      return new Result(true, "success",
            CollectionUtils.newObjectMap("CompleteCount", CompleteCount, "UndoneCount", UndoneCount));
   }
   @Override
   public Result lstSubjectDetail(String userId) {
//      String userId = ClientUtils.getUserId();
      StringBuffer hql = new StringBuffer(
            "select percent as percent,className as className ,id.classId as classId ,id.subjectId as subjectId ,"
                  + "subjectName as subjectName ,coverPageUrl as coverPageUrl , progressValue as progressValue from"
                  + " MySubjectV p where p.id.userId =:userId and p.subjectStatus=:subjectStatus ");
      Map<String, Object> args = CollectionUtils.newObjectMap("userId", userId,"subjectStatus",Subject.STATUS_ISSUED);
      List<Map<String, Object>> subjectLstMap = findListWithMapByHql(hql.toString(), args);
      for (Map<String, Object> subject : subjectLstMap) {
         String classId = (String) subject.get("classId");
         String subjectId = (String) subject.get("subjectId");
         Map<String, Object> map = progressDao.getStudyById(userId, subjectId, classId);
         subject.put("lectureParentId", map.get("lectureParentId"));
         subject.put("lectureId", map.get("lectureId"));
         subject.put("unCommitExerciseCount", exerciseInfoService.getUnCommitExerciseCount(classId, userId));
         subject.put("toBeCommitExerciseCount", exerciseInfoService.getToBeCommitExerciseCount(classId, userId));
         subject.put("CommitExerciseCount", exerciseInfoService.getCommitExerciseCount(classId, userId));
         subject.put("exerciseCount", exerciseInfoService.getExerciseCount(classId, userId));
         subject.put("examCount", examService.getExamCount(classId, userId));
         subject.put("unCommitExamCount", examService.getUnCommitExamCount(classId, userId));
         subject.put("commitExamCount", examService.getCommitExamCount(classId, userId));
         subject.put("toBeCommitExamCount", examService.getToBeCommitExamCount(classId, userId));
      }
      return new Result(true, "success", subjectLstMap);
   }
   @SuppressWarnings({ "unchecked", "rawtypes" })
   @Override
   public Result getDataDesc(String classId, String subjectId) {
      if(StringUtils.isEmpty(classId)) {
         return new Result(false, "班级id参数错误");
      }
      QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
      List<Map<String, Object>> percentDesc = this.percentDesc(classId, subjectId, new OrderSpecifier(Order.DESC, qSubjectProgressTreeV.percent));
      List<Map<String, Object>> studyTimeDesc = this.percentDesc(classId, subjectId, new OrderSpecifier(Order.DESC, qSubjectProgressTreeV.progressValue));
      List<Map<String, Object>> exerciseInfoDesc = this.exerciseInfoDesc(classId, subjectId);
      List<Map<String, Object>> examInfoDesc = this.examInfoDesc(classId, subjectId);
      return new Result(true, "success", CollectionUtils.newObjectMap("percentDesc", percentDesc, "studyTimeDesc",
            studyTimeDesc, "exerciseInfoDesc", exerciseInfoDesc, "examInfoDesc", examInfoDesc));
   }
   /**
    * 获取班级对应的学员 按进度进行排序
    */
   private List<Map<String, Object>> percentDesc(String classId, String subjectId, @SuppressWarnings("rawtypes") OrderSpecifier order) {
      QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
      QUser qUser = QUser.user;
      String nodeId = StringUtils.isNotEmpty(subjectId)?subjectId:classId;
      String nodeType = StringUtils.isNotEmpty(subjectId)?Progress.PROGRESS_TYPE_SUBJECT:Progress.PROGRESS_TYPE_CLASS;
      List<Map<String, Object>> lstMap = this.getQueryFactory().select(qSubjectProgressTreeV.progressValue,
            qSubjectProgressTreeV.percent, qUser.name, qUser.userId,qSubjectProgressTreeV.id.nodeId).from(qSubjectProgressTreeV, qUser).
            where(qSubjectProgressTreeV.id.userId.eq(qUser.userId).and(qSubjectProgressTreeV.nodeType.eq(nodeType))
                  .and(qSubjectProgressTreeV.id.nodeId.eq(nodeId))).orderBy(order).fetch().stream().map(tuple -> {
                     Map<String, Object> map = new HashMap<>();
                     map.put("userName", tuple.get(qUser.name));
                     map.put("userId", tuple.get(qUser.userId));
                     map.put("classId", tuple.get(qSubjectProgressTreeV.id.nodeId));
                     map.put("percent", tuple.get(qSubjectProgressTreeV.percent));
                     map.put("progressValue", tuple.get(qSubjectProgressTreeV.progressValue));
                     return map;
                  }).collect(Collectors.toList());
      return lstMap;
   }
   /**
    * 通过作业完成个数排序
    *
    */
   private List<Map<String, Object>> exerciseInfoDesc(String classId, String subjectId) {
      QExerciseResultV qExerciseResultV = QExerciseResultV.exerciseResultV;
      //查询条件
      Predicate predicate = StringUtils.isEmpty(subjectId)?qExerciseResultV.id.classId.eq(classId):
         qExerciseResultV.id.classId.eq(classId).and(qExerciseResultV.subjectId.eq(subjectId));
      //case数量判断
      NumberExpression<BigDecimal> caseCount = new CaseBuilder()
      .when(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
            .or(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
      .then(BigDecimal.ONE).otherwise(BigDecimal.ZERO).sum();
      //case分数
      NumberExpression<BigDecimal> caseScoreSum = new CaseBuilder()
            .when(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
                  .or(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
            .then(qExerciseResultV.score).otherwise(BigDecimal.ZERO).sum();
      List<Map<String, Object>> lstMap = this.getQueryFactory().select(qExerciseResultV.userId,qExerciseResultV.studentName,
            caseScoreSum.divide(caseCount), qExerciseResultV.count(), caseCount).from(qExerciseResultV).where(predicate).
            groupBy(qExerciseResultV.userId).
            orderBy(caseScoreSum.divide(caseCount).desc()).fetch().stream().map(tuple ->{
               Map<String, Object> map = new HashMap<>();
               map.put("userId", tuple.get(qExerciseResultV.userId));
               map.put("userName", tuple.get(qExerciseResultV.studentName));
               map.put("avgScore", tuple.get(2, BigDecimal.class));
               map.put("exerciseCount",tuple.get(3, BigDecimal.class));
               map.put("commitExerciseCount", tuple.get(4, BigDecimal.class));
               return map;
            }).collect(Collectors.toList());
      return lstMap;
   }
   /**
    *
    */
   private List<Map<String, Object>> examInfoDesc(String classId, String subjectId) {
      QExamResultV qExamResultV = QExamResultV.examResultV;
      //查询条件
      Predicate predicate = StringUtils.isEmpty(subjectId)?qExamResultV.id.classId.eq(classId):
         qExamResultV.id.classId.eq(classId).and(qExamResultV.subjectId.eq(subjectId));
      //case判断
      NumberExpression<BigDecimal> caseCount = new CaseBuilder()
             .when(qExamResultV.status.eq("0")).then(BigDecimal.ZERO).otherwise(BigDecimal.ONE).sum();
      //case分数
      NumberExpression<BigDecimal> caseScoreSum = new CaseBuilder()
            .when(qExamResultV.status.eq("0")).then(BigDecimal.ZERO).otherwise(qExamResultV.score).sum();
      List<Map<String, Object>> lstMap = this.getQueryFactory().select(qExamResultV.userId,qExamResultV.studentName,
            caseScoreSum.divide(caseCount), qExamResultV.count(), caseCount).from(qExamResultV).where(predicate).
            groupBy(qExamResultV.userId).
            orderBy(caseScoreSum.divide(caseCount).desc()).fetch().stream().map(tuple ->{
               Map<String, Object> map = new HashMap<>();
               map.put("userId", tuple.get(qExamResultV.userId));
               map.put("userName", tuple.get(qExamResultV.studentName));
               map.put("avgScore", tuple.get(2, BigDecimal.class));
               map.put("examCount",tuple.get(3, BigDecimal.class));
               map.put("commitExamCount", tuple.get(4, BigDecimal.class));
               return map;
            }).collect(Collectors.toList());
      return lstMap;
   }
   @Override
   public Result lastStudied(String userId) {
      Map<String, Object> map = progressDao.getStudyByUserId(userId);
      String subjectId = (String) map.get("subjectId");
      Subject subject = read(Subject.class, subjectId);
      if (subject != null) {
         map.put("subjectName", subject.getName());
      }
      return new Result(true, "success", map);
   }
   @Override
   public List<Map<String,Object>> queryAvailableSubjectIdAndName(String teacherId,Integer subjectType){
      List<Map<String,Object>> result = null;
      if(subjectType==Subject.TYPE_PUBLIC_SUBJECT){
         result =  this.findListWithMapByHql(
               "select subjectId as subjectId ,name as subjectName from Subject where deleteFlag is false and type=" + Subject.TYPE_PUBLIC_SUBJECT + " and orgId='" + ClientUtils.getOrgId() + "'" , null);
      }else{
         if(StringUtils.isNotEmpty(teacherId)){
             result =  this.findListWithMapByHql(
                     "select distinct origSubjectId as subjectId ,name as subjectName from Subject where deleteFlag is false and type=" + Subject.TYPE_CLS_SUBJECT + " and teacherId='" + teacherId + "'", null);
         }else{
             result =  this.findListWithMapByHql(
                     "select subjectId as subjectId ,name as subjectName from Subject where deleteFlag is false and type=" + Subject.TYPE_ORG_SUBJECT + " and orgId='" + ClientUtils.getOrgId() + "'", null);
         }
      }
      return result;
   }
   @Override
   public List<Map<String, Object>> getMySubjectList() {
      String sql = "SELECT o.CLASS_ID, a.`NAME` AS subjectName, a.SUBJECT_ID, o.`NAME` AS className FROM ( ( SELECT "
            + "c.CLASS_ID, c.`NAME` FROM stu_student s, cls_class c WHERE s.CLASS_ID = c.CLASS_ID AND s.USER_ID =:userId"
            + " ) o LEFT JOIN ( SELECT r.class_id,s.SUBJECT_ID, s.`NAME` FROM `subject` s, cls_class_re_subject r WHERE "
            + "s.SUBJECT_ID = r.subject_id ) a ON o.CLASS_ID = a.class_id ) ";
      List<Object[]> list = findByComplexSql(sql, CollectionUtils.newObjectMap("userId", ClientUtils.getUserId()),
            Object[].class);
      List<Map<String, Object>> lstMap = new ArrayList<Map<String, Object>>(list.size());
      Map<String, Object> map = null;
      for (Object[] objects : list) {
         map = new HashMap<String, Object>(objects.length);
         map.put("classId", objects[0]);
         map.put("subjectName", objects[1]);
         map.put("subjectId", objects[2]);
         map.put("className", objects[3]);
         lstMap.add(map);
      }
      return lstMap;
   }
   @Override
   public List<Map<String,Object>> clsSubjectlist(String classId, Integer schoolYear, Integer term) {
      QSubject qSubject = QSubject.subject;
      QClsClassReSubject qClsClassReSubject = QClsClassReSubject.clsClassReSubject;
      QueryDslOptionBuilder builder = new QueryDslOptionBuilder().
            and(qSubject.deleteFlag::eq, false)
            .and(qClsClassReSubject.classId::eq, classId)
            .and(qClsClassReSubject.subjectId::eq, qSubject.subjectId)
            .and(qClsClassReSubject.deleteFlag::eq, false).and(qSubject.status::eq, Subject.STATUS_ISSUED);
      if(schoolYear != null && schoolYear != 0){//学年
         builder = builder.and(qSubject.schoolYear::eq, schoolYear);
      }
      if(term != null && term != 0){//学期
         builder = builder.and(qSubject.term::eq, term);
      }
      return this.getQueryFactory().select(qSubject.name,qSubject.origSubjectId,qSubject.subjectId,qSubject.schoolYear, qSubject.term).distinct()
             .from(qSubject, qClsClassReSubject)
             .where(builder.build())
             .orderBy(qSubject.createTime.desc())
             .fetch().stream()
             .map(tuple -> {
                Map<String,Object> map = new HashMap<String,Object>(2);
                map.put("name", tuple.get(qSubject.name));
                map.put("subjectId",  tuple.get(qSubject.subjectId));
                map.put("schoolYear",  tuple.get(qSubject.schoolYear));
                map.put("term",  tuple.get(qSubject.term));
                map.put("origSubjectId",  tuple.get(qSubject.origSubjectId));
                return map;
             }).collect(Collectors.toList());
   }
   @Override
   public List<Map<String,Object>> termList(String classId) {
      QSubject qSubject = QSubject.subject;
      QClsClassReSubject qClsClassReSubject = QClsClassReSubject.clsClassReSubject;
      QueryDslOptionBuilder builder = new QueryDslOptionBuilder().
            and(qSubject.deleteFlag::eq, false)
            .and(qClsClassReSubject.classId::eq, classId)
            .and(qClsClassReSubject.subjectId::eq, qSubject.subjectId)
            .and(qClsClassReSubject.deleteFlag::eq, false).and(qSubject.status::eq, Subject.STATUS_ISSUED);
      return this.getQueryFactory().select(qSubject.schoolYear.as("schoolYear"),qSubject.term.as("term"))
             .from(qSubject, qClsClassReSubject)
             .where(builder.build().and(qSubject.schoolYear.isNotNull())
                   .and(qSubject.term.isNotNull())).groupBy(qSubject.schoolYear, qSubject.term)
             .orderBy(qSubject.schoolYear.desc(), qSubject.term.desc())
             .fetch().stream()
             .map(tuple -> {
                Map<String,Object> map = new HashMap<String,Object>(2);
                map.put("schoolYear", tuple.get(0, Integer.class));
                map.put("term",  tuple.get(1, Integer.class));
                return map;
             }).collect(Collectors.toList());
   }
   /**
    * 我的班级信息
    *
    * @param classId
    * @return
    */
   public Map<String,Object> myClassInfo(String classId){
      ClsClass objClsClass = this.read(ClsClass.class, classId);
      QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
      List<Subject> lstSubject = objClsClass.getSubjects();
      //过滤掉状态为草稿的
      List<String> teachers = lstSubject.stream().filter(u->u.getStatus().equals(Subject.STATUS_ISSUED)).map(tuple -> {
         return tuple.getTeacherName();
      }).collect(Collectors.toList());
      SubjectProgressTreeV objSubjectProgressTreeV = this.getQueryFactory().selectFrom(qSubjectProgressTreeV)
            .where(qSubjectProgressTreeV.id.nodeId.eq(classId).and(qSubjectProgressTreeV.id.userId.eq(ClientUtils.getUserId())).and(qSubjectProgressTreeV.nodeType.eq("class"))).fetchOne();
      if(objSubjectProgressTreeV != null) {
         long allCount = this.getQueryFactory().selectFrom(qSubjectProgressTreeV)
               .where(qSubjectProgressTreeV.id.nodeId.eq(classId)).fetchCount();
         long lgCount = this.getQueryFactory().selectFrom(qSubjectProgressTreeV)
               .where(qSubjectProgressTreeV.id.nodeId.eq(classId).and(qSubjectProgressTreeV.percent.gt(objSubjectProgressTreeV.getPercent()))).fetchCount();
         //排行
         float rank = (allCount-lgCount)/allCount;
         return CollectionUtils.newObjectMap("className", objClsClass.getName(), "progressPercent",
               objSubjectProgressTreeV.getPercent(), "progressValue", objSubjectProgressTreeV.getProgressValue(), "rank", rank, "teacherName", teachers);
      }else {
         return CollectionUtils.newObjectMap("className", objClsClass.getName(), "percent",
               0, "progressValue", 0, "rank", 0, teachers);
      }
   }
   /**
    * 获取我的课程进度
    *
    * @param classId
    * @return
    */
   public List<Map<String,Object>> myClsSubjectlist(String classId, String userId,  Pager pager){
      String teacherId = this.teacherService.getTeacherIdByUserId(ClientUtils.getUserId());
      QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
      Predicate predicate = null;
      if(StringUtils.isNotEmpty(teacherId)) {
         predicate = qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(userId)).and(qMySubjectV.teacherId.eq(teacherId).and(qMySubjectV.subjectStatus.eq(Subject.STATUS_ISSUED)));
      }else {
         predicate = qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(userId).and(qMySubjectV.subjectStatus.eq(Subject.STATUS_ISSUED)));
      }
      return this.getQueryFactory().select(qMySubjectV.id.subjectId,
            qMySubjectV.subjectName,qMySubjectV.term,
            qMySubjectV.schoolYear,qMySubjectV.percent, qMySubjectV.coverPageUrl,qMySubjectV.origSubjectId)
             .from(qMySubjectV)
             .where(predicate)
             .orderBy(qMySubjectV.schoolYear.desc(),qMySubjectV.term.desc())
             .limit(pager.getPageSize()).offset(pager.getOffset())
             .fetch().stream()
             .map(tuple -> {
                Map<String,Object> map = new HashMap<String,Object>(5);
                map.put("name", tuple.get(qMySubjectV.subjectName));
                map.put("origSubjectId",  tuple.get(qMySubjectV.origSubjectId));
                map.put("subjectId",  tuple.get(qMySubjectV.id.subjectId));
                map.put("progressPercent",  tuple.get(qMySubjectV.percent));
                map.put("schoolYear",  tuple.get(qMySubjectV.schoolYear));
                map.put("term",  tuple.get(qMySubjectV.term));
                map.put("coverPageUrl",  tuple.get(qMySubjectV.coverPageUrl));
                return map;
             }).collect(Collectors.toList());
   }
   /**
    * 获取我的课程数量
    *
    * @param classId
    * @return
    */
   public long myClsSubjectCount(String classId){
      QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
      return this.getQueryFactory().select(qMySubjectV.id.subjectId,
            qMySubjectV.subjectName,qMySubjectV.term,
            qMySubjectV.schoolYear,qMySubjectV.percent)
             .from(qMySubjectV)
             .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(ClientUtils.getUserId())).and(qMySubjectV.subjectStatus.eq(Subject.STATUS_ISSUED)))
             .fetchCount();
   }
   /**
    * 获取学员的课程进度
    *
    * @param classId
    * @return
    */
   public List<Map<String,Object>> studentSubjectProgress(String classId, Pager pager){
      String teacherId = this.teacherService.getTeacherIdByUserId(ClientUtils.getUserId());
      QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
      QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
      return this.getQueryFactory().select(qMySubjectV.id.subjectId,
            qMySubjectV.subjectName,qMySubjectV.term,qMySubjectV.coverPageUrl,
            qMySubjectV.schoolYear,qMySubjectV.lectureCount, qMySubjectV.percent.avg().as(qMySubjectV.percent))
             .from(qMySubjectV)
             .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.teacherId.eq(teacherId)))
             .groupBy(qMySubjectV.id.subjectId)
             .orderBy(qMySubjectV.schoolYear.desc(),qMySubjectV.term.desc())
             .limit(pager.getPageSize()).offset(pager.getOffset())
             .fetch().stream()
             .map(tuple -> {
                Map<String,Object> map = new HashMap<String,Object>(5);
                map.put("name", tuple.get(qMySubjectV.subjectName));
                map.put("subjectId",  tuple.get(qMySubjectV.id.subjectId));
                map.put("schoolYear",  tuple.get(qMySubjectV.schoolYear));
                map.put("term",  tuple.get(qMySubjectV.term));
                map.put("progressPercent",
                     this.getQueryFactory().select(qSubjectProgressTreeV.percent.avg())
                           .from(qSubjectProgressTreeV)
                           .where(qSubjectProgressTreeV.id.nodeId.eq(tuple.get(qMySubjectV.id.subjectId))
                                 .and(qSubjectProgressTreeV.nodeType.eq(Progress.PROGRESS_TYPE_SUBJECT)))
                           .groupBy(qSubjectProgressTreeV.id.nodeId).fetchOne());
                map.put("coverPageUrl",  tuple.get(qMySubjectV.coverPageUrl));
                map.put("lectureCount",  this.getLectureCount(tuple.get(qMySubjectV.id.subjectId)));
                return map;
             }).collect(Collectors.toList());
   }
   /**
    * 获取课件数量
    *
    * @param subjectId
    * @return
    */
   public long getLectureCount(String subjectId) {
      Subject subject = this.read(subjectId);
      if(subject == null) {
         return 0l;
      }
      if(subject.getType() == Subject.TYPE_CLS_SUBJECT) {//班级课程
         QClsSubjectLecture qSubjectLecture = QClsSubjectLecture.clsSubjectLecture;
         return this.getQueryFactory().selectFrom(qSubjectLecture).where(qSubjectLecture.deleteFlag.isFalse()
                .and(qSubjectLecture.subjectId.eq(subjectId)).and(qSubjectLecture.status.eq(SubjectLecture.STATUS_DRAFT))).fetchCount();
      }else {
         QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
         return this.getQueryFactory().selectFrom(qSubjectLecture).where(qSubjectLecture.deleteFlag.isFalse()
                .and(qSubjectLecture.subjectId.eq(subjectId)).and(qSubjectLecture.status.eq(SubjectLecture.STATUS_DRAFT))).fetchCount();
      }
   }
   /**
    * 我的公开课列表
    *
    * @param pageNum
    * @param pageSize
    * @param keyword
    * @return
    */
   public Map<String,Object> myOpenSubjectList(Integer pageNum, Integer pageSize, String keyword){
      QSubject qSubject = QSubject.subject;
      QProgress qProgress = QProgress.progress;
      QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
      JPAQuery<Tuple> query = this.getQueryFactory()
            .select(qSubject.subjectId, qSubject.name, qSubject.term,qSubject.coverPageUrl, qSubject.schoolYear,
                  qProgress.progressPercent.avg().as(qProgress.progressPercent), qProgress.progressValue.sum().as(qProgress.progressValue))
            .from(qSubject, qProgress, qSubjectLecture )
            .where(qSubject.deleteFlag.isFalse().and(qSubjectLecture.subjectId.eq(qSubject.subjectId))
                  .and(qSubjectLecture.deleteFlag.isFalse()).and(qSubjectLecture.lectureId.eq(qProgress.targetId))
                  .and(qProgress.learnerId.eq(ClientUtils.getUserId()))
                  .and(qSubject.name.like("%" + keyword + "%").and(qProgress.deleteFlag.isFalse()))
                  .and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE)).and(qSubject.status.eq(Subject.STATUS_ISSUED))).groupBy(qSubject.subjectId);
      long count = query.fetchCount();
      List<Map<String, Object>> listData = query.orderBy(qProgress.createTime.desc()).limit(pageSize).offset(pageNum).fetch().stream().map(tuple -> {
               Map<String, Object> map = new HashMap<String, Object>(7);
               String subjectId = tuple.get(qSubject.subjectId);
               map.put("name", tuple.get(qSubject.name));
               map.put("subjectId", subjectId);
               map.put("schoolYear", tuple.get(qSubject.schoolYear));
               map.put("term", tuple.get(qSubject.term));
               map.put("coverPageUrl", tuple.get(qSubject.coverPageUrl));
               map.put("progressPercent", tuple.get(qProgress.progressPercent));
               map.put("progressValue", tuple.get(qProgress.progressValue));
               Map<String,Object> openSubjectDetail = this.openSubjectDetail(subjectId);
               // 直播数量
               map.put("mediaVideoLiveCount",openSubjectDetail.get("mediaVideoLiveCount"));
               // 课件数量
               map.put("subjectLectureCount",openSubjectDetail.get("subjectLectureCount"));
               //学习人次
               map.put("studyCount",openSubjectDetail.get("studyCount"));
               map.put("content",openSubjectDetail.get("content"));
               // 已观看完成课件数量
               map.put("subjectLectureDoCount",openSubjectDetail.get("subjectLectureDoCount"));
               return map;
            }).collect(Collectors.toList());
      return CollectionUtils.newObjectMap("count", count, "listData", listData);
   }
   /**
    * 课程统计详情
    *
    * @param subjectId
    * @return
    */
   public Map<String,Object> openSubjectDetail(String subjectId){
      Map<String, Object> map = new HashMap<String, Object>();
      QMediaVideoLive qMediaVideoLive = QMediaVideoLive.mediaVideoLive;
      QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
      QProgress qProgress = QProgress.progress;
      // 直播数量
      map.put("mediaVideoLiveCount",
            this.getQueryFactory().select(qMediaVideoLive).from(qMediaVideoLive)
                  .where(qMediaVideoLive.deleteFlag.isFalse()
                        .and(qMediaVideoLive.status.gt(0))
                        .and(qMediaVideoLive.subjectId.eq(subjectId)))
                  .fetchCount());
      // 课件数量
      map.put("subjectLectureCount",
            this.getQueryFactory().select(qSubjectLecture).from(qSubjectLecture)
                  .where(qSubjectLecture.deleteFlag.isFalse()
                        .and(qSubjectLecture.subjectId.eq(subjectId)).and(qSubjectLecture.status.eq(SubjectLecture.STATUS_DRAFT)))
                  .fetchCount());
      //学习人次
      map.put("studyCount",
            this.getQueryFactory().selectDistinct(qProgress.learnerId).from(qProgress, qSubjectLecture)
                  .where(qProgress.deleteFlag.isFalse().and(qSubjectLecture.deleteFlag.isFalse()).and(qSubjectLecture.subjectId.eq(subjectId)).and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE))
                        .and(qProgress.targetId.eq(qSubjectLecture.lectureId)))
                  .fetchCount());
      map.put("content", this.readSubjectContent(subjectId));
      // 已观看完成课件数量
      map.put("subjectLectureDoCount",
            this.getQueryFactory().select(qSubjectLecture).from(qSubjectLecture, qProgress)
                  .where(qSubjectLecture.deleteFlag.isFalse().and(qProgress.deleteFlag.isFalse())
                        .and(qProgress.learnerId.eq(ClientUtils.getUserId())).and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE))
                        .and(qProgress.progressPercent.gt(0.95)).and(qProgress.targetId.eq(qSubjectLecture.lectureId))
                        .and(qSubjectLecture.subjectId.eq(subjectId)))
                  .fetchCount());
      return map;
   }
   /**
    * 公开课详情
    *
    * @param subjectId
    * @return
    */
   public Map<String,Object> openSubjectInfo(String subjectId){
      QProgress qProgress = QProgress.progress;
      QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
      Subject objSubject = this.read(subjectId);
      Tuple progress = this.getQueryFactory()
            .select(qProgress.progressPercent.sum().as(qProgress.progressPercent), qProgress.progressValue.sum().as(qProgress.progressValue)).from(qProgress,qSubjectLecture).where(qProgress.learnerId.eq(ClientUtils.getUserId())
                        .and(qProgress.targetId.eq(qSubjectLecture.lectureId))
                  .and(qProgress.deleteFlag.isFalse()).and(qSubjectLecture.deleteFlag.isFalse()).and(qSubjectLecture.subjectId.eq(subjectId))
                  .and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE))).fetchOne();
      Map<String, Object> subjectInfo = new HashMap<String, Object>(7);
      subjectInfo.put("name", objSubject.getName());
      subjectInfo.put("subjectId", subjectId);
      subjectInfo.put("schoolYear", objSubject.getSchoolYear());
      subjectInfo.put("term", objSubject.getTerm());
      subjectInfo.put("coverPageUrl", objSubject.getCoverPageUrl());
      subjectInfo.put("teacherName", objSubject.getTeacherName());
      Map<String,Object> openSubjectDetail = this.openSubjectDetail(subjectId);
      Map<String, Object> map = new HashMap<String, Object>(7);
      // 直播数量
      map.put("mediaVideoLiveCount",openSubjectDetail.get("mediaVideoLiveCount"));
      // 课件数量
      map.put("subjectLectureCount",openSubjectDetail.get("subjectLectureCount"));
      //学习人次
      map.put("studyCount",openSubjectDetail.get("studyCount"));
      subjectInfo.put("content",openSubjectDetail.get("content"));
      // 已观看完成课件数量
      map.put("subjectLectureDoCount",openSubjectDetail.get("subjectLectureDoCount"));
      map.put("subjectInfo", subjectInfo);
      if(openSubjectDetail.get("subjectLectureCount") == null || progress == null || progress.get(qProgress.progressPercent) == null) {
         subjectInfo.put("progressPercent", 0);
      }else {
         subjectInfo.put("progressPercent", progress.get(qProgress.progressPercent).floatValue()/(Long)openSubjectDetail.get("subjectLectureCount"));
      }
      subjectInfo.put("progressValue", progress == null?0:progress.get(qProgress.progressValue));
      return map;
   }
   @Override
   public Map<String, Object> mySubjectInfo(String subjectId, String classId) {
      QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
      QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
      // 课程
      Tuple tuple = this.getQueryFactory()
            .select(qMySubjectV.id.subjectId, qMySubjectV.subjectName, qMySubjectV.term, qMySubjectV.schoolYear,qMySubjectV.origSubjectId,
                  qMySubjectV.percent,qMySubjectV.coverPageUrl, qMySubjectV.progressValue)
            .from(qMySubjectV)
            .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(ClientUtils.getUserId()))
                  .and(qMySubjectV.id.subjectId.eq(subjectId)))
            .fetchOne();
      Subject objSubject = this.read(subjectId);
      Map<String, Object> subject = new HashMap<String, Object>(5);
      subject.put("name", objSubject.getName());
      subject.put("subjectId", subjectId);
      subject.put("origSubjectId", objSubject.getOrigSubjectId());
      subject.put("schoolYear", objSubject.getSchoolYear());
      subject.put("term", objSubject.getTerm());
      subject.put("coverPageUrl", objSubject.getCoverPageUrl());
      subject.put("content", this.readSubjectContent(subjectId));
      subject.put("teacherName", objSubject.getTeacherName());
      if(tuple == null) {
         subject.put("progressPercent", 0);
         subject.put("progressValue", 0);
      }else {
         subject.put("progressPercent", tuple.get(qMySubjectV.percent));
         subject.put("progressValue", tuple.get(qMySubjectV.progressValue));
      }
      String origSubjectId = objSubject.getOrigSubjectId();
      // 考试统计
      long examsCount = this.examService.listStudentExamCount("", new String[] {classId}, origSubjectId, null);
      // 作业统计
      long homeworksCount = exerciseInfoService.queryStuExerciseListCount("", null, ClientUtils.getUserId(), origSubjectId, null);
      // 课件统计
      Tuple tupleLecture = this.getQueryFactory().select(qMyLectureV.count(),
            new CaseBuilder().when(qMyLectureV.percent.gt(0.95)).then(1).otherwise(0).sum()).// 大于95%算完成
            from(qMyLectureV)
            .where(qMyLectureV.classId.eq(classId).and(qMyLectureV.id.userId.eq(ClientUtils.getUserId()))
                  .and(qMyLectureV.subjectId.eq(subjectId)))
            .groupBy(qMyLectureV.subjectId).fetchOne();
      long mediaVideoLivesCount = this.mediaLiveService.listCount("", new String[] {classId}, origSubjectId, null);
      return CollectionUtils.newObjectMap("mediaVideoLivesCount", mediaVideoLivesCount, "examsCount", examsCount,
            "homeworksCount", homeworksCount, "subjectInfo", subject, "lectureCount",
            tupleLecture == null?0:tupleLecture.get(0, Long.class),
            "completeLectureCount", tupleLecture == null?0:tupleLecture.get(1,Integer.class));
   }
   /**
    * 公开课列表
    *
    * @param pageNum
    * @param pageSize
    * @param keyword
    * @return
    */
   public Map<String,Object> openSubjectList(Integer pageNum, Integer pageSize, String keyword){
      QOpenSubjectV qOpenSubjectV = QOpenSubjectV.openSubjectV;
      JPAQuery<OpenSubjectV> query = this.getQueryFactory().selectFrom(qOpenSubjectV).where(qOpenSubjectV.subjectName.like("%" + keyword + "%"));
      long count = query.fetchCount();
      List<Map<String, Object>> listData = query.orderBy(qOpenSubjectV.mediaVideoCount.desc(),
            qOpenSubjectV.learnerCount.desc(), qOpenSubjectV.createTime.desc()).limit(pageSize).offset(pageNum)
            .fetch().stream().map(tuple -> {
               Map<String, Object> map = new HashMap<String, Object>(8);
               map.put("name", tuple.getSubjectName());
               map.put("subjectId", tuple.getSubjectId());
               map.put("schoolYear", tuple.getSchoolYear());
               map.put("term", tuple.getTerm());
               map.put("coverPageUrl", tuple.getCoverPageUrl());
               map.put("mediaVideoCount", tuple.getMediaVideoCount());
               map.put("learnerCount", tuple.getLearnerCount());
               map.put("createTime", tuple.getCreateTime());
               return map;
            }).collect(Collectors.toList());
      return CollectionUtils.newObjectMap("count", count, "listData", listData);
   }
   /**
    * 班级学员课件总体进度
    *
    * @param subjectId
    * @param classId
    * @return
    */
   @Override
    public List<Map<String, Object>> studentSubjectLectureProgress(String subjectId, String classId) {
       QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
      return this.getQueryFactory()
            .select(qMyLectureV.lectureName, qMyLectureV.id.lectureId, qMyLectureV.lectureType,
                  qMyLectureV.chapterId, qMyLectureV.subjectId, qMyLectureV.lectureCreateTime,
                  qMyLectureV.percent.avg().as(qMyLectureV.percent))
            .from(qMyLectureV).where(qMyLectureV.classId.eq(classId).and(qMyLectureV.subjectId.eq(subjectId)))
            .groupBy(qMyLectureV.id.lectureId).orderBy(qMyLectureV.lectureCreateTime.desc()).fetch().stream()
            .map(tuple -> {
               Map<String, Object> map = new HashMap<String, Object>(6);
               map.put("lectureName", tuple.get(qMyLectureV.lectureName));
               map.put("lectureId", tuple.get(qMyLectureV.id.lectureId));
               map.put("lectureType", tuple.get(qMyLectureV.lectureType));
               map.put("chapterId", tuple.get(qMyLectureV.chapterId));
               map.put("subjectId", tuple.get(qMyLectureV.subjectId));
               map.put("progressPercent", tuple.get(qMyLectureV.percent));
               map.put("createTime", tuple.get(qMyLectureV.lectureCreateTime));
               return map;
            }).collect(Collectors.toList());
    }
   /**
    * 学员课程作业进度
    *
    * @param classId
    * @param subjectId
    * @return
    */
   public Map<String, Object> studentSubjectHomeworkProgress(String classId, String subjectId, String studentId){
      QExerciseResultV qHomeworkScoreV = QExerciseResultV.exerciseResultV;
      StuStudent student = read(StuStudent.class, studentId);
      Subject subject = read(Subject.class, subjectId);
    @Override
    public Result updateClsSubject(String classId, String subjectId, String origSubjectId, String teacherId, Integer schoolYear, Integer term) {
        Subject origSubject = this.read(origSubjectId);
        Subject subject = this.read(subjectId);
        UserTeacher teacher = this.read(UserTeacher.class, teacherId);
      Tuple tuple = this.getQueryFactory()
            .select(qHomeworkScoreV.subjectId, qHomeworkScoreV.count(),
                  new CaseBuilder()
                        .when(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
                              .or(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
                        .then(qHomeworkScoreV.studentScore).otherwise(BigDecimal.ZERO).sum(),
                  new CaseBuilder()
                        .when(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
                              .or(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
                        .then(1).otherwise(0).sum())
            .from(qHomeworkScoreV)
            .where(qHomeworkScoreV.subjectId.eq(subject.getOrigSubjectId())
                  .and(qHomeworkScoreV.userId.eq(student.getUserId()))
                  .and(qHomeworkScoreV.exerciseStatus.eq(ExerciseInfo.EXERCISE_STATUS_PUBLISHED)))
            .groupBy(qHomeworkScoreV.userId).fetchOne();
      Map<String,Object> map = new HashMap<String,Object>(4);
      if(tuple == null) {
         map.put("subjectId", subjectId);
         map.put("homeworkCount",  0);
         map.put("avgScore",  "0");
         map.put("commitHomeworkCount",  0);
       }else {
          int commitHomeworkCount = tuple.get(3, Integer.class) == null?0:tuple.get(3, Integer.class);
          map.put("subjectId", subjectId);
          map.put("homeworkCount",  tuple.get(1, Integer.class) == null?0:tuple.get(1, Integer.class));
          map.put("avgScore",  String.valueOf(commitHomeworkCount == 0 || tuple.get(2, BigDecimal.class) == null?BigDecimal.ZERO:tuple.get(2, BigDecimal.class).divide(BigDecimal.valueOf(commitHomeworkCount), 2, BigDecimal.ROUND_HALF_UP)));
          map.put("commitHomeworkCount", commitHomeworkCount);
       }
       return map;
   }
   /**
    * 学员考试作业进度
    *
    * @param classId
    * @param subjectId
    * @return
    */
   public Map<String, Object> studentSubjectExamProgress(String classId, String subjectId, String studentId){
      QExamResultV qExamScoreV = QExamResultV.examResultV;
        //如果原课程做出了修改
        if (!origSubjectId.equals(subject.getOrigSubjectId())) {
            subject.setContentFileId(origSubject.getCoverPageFileId());
            subject.setCoverPageUrl(origSubject.getCoverPageUrl());
            subject.setContentFileId(origSubject.getContentFileId());
            subject.setName(origSubject.getName());
            subject.setOrigSubjectId(origSubjectId);
            subject.setOrigCopySubjectId(origSubjectId);
      StuStudent student = read(StuStudent.class, studentId);
      Subject subject = read(Subject.class, subjectId);
      Tuple tuple = this.getQueryFactory().select(qExamScoreV.subjectId, qExamScoreV.count(), new CaseBuilder()
             .when(qExamScoreV.status.eq("0")).then(BigDecimal.ZERO).otherwise(qExamScoreV.score).sum(), new CaseBuilder()
             .when(qExamScoreV.status.eq("0")).then(0).otherwise(1).sum()).
            from(qExamScoreV).
            where(qExamScoreV.subjectId.eq(subject.getOrigSubjectId()).and(qExamScoreV.userId.eq(student.getUserId())).and(qExamScoreV.examStatus.eq(ExerciseInfo.EXERCISE_STATUS_PUBLISHED))).
            groupBy(qExamScoreV.userId).fetchOne();
       Map<String,Object> map = new HashMap<String,Object>(4);
       map.put("subjectId", subjectId);
       if(tuple == null) {
          map.put("examCount",  0);
           map.put("avgScore",  "0");
           map.put("commitExamCount",  0);
       }else {
          int commitExamCount = tuple.get(3, Integer.class) == null?0:tuple.get(3, Integer.class);
          map.put("examCount",  tuple.get(1, Integer.class) == null?0:tuple.get(1, Integer.class));
           map.put("avgScore",  String.valueOf(commitExamCount == 0 || tuple.get(2, BigDecimal.class) == null?BigDecimal.ZERO:tuple.get(2, BigDecimal.class).divide(new BigDecimal(commitExamCount), 2, BigDecimal.ROUND_HALF_UP)));
           map.put("commitExamCount",  tuple.get(3, Integer.class) == null?0:tuple.get(3, Integer.class));
       }
      return map;
   }
   /**
    * 我的课件情况
    *
    * @param classId
    * @return
    */
   private List<Map<String, Object>> myLectureList(String classId){
      QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
            //清理并复制原课程
            clsLectureService.doClearLecturesToClass(classId, subjectId);
            clsLectureService.doCopyLecturesToClass(origSubjectId, subjectId, classId);
        } else {
            clsLectureService.doClearLecturesToClass(classId, subjectId);
            clsLectureService.doCopyLecturesToClass(origSubjectId, subjectId, classId);
        }
        TraceUtils.setUpdateTrace(subject);
        subject.setTeacherId(teacherId);
        subject.setTeacherName(teacher.getName());
        subject.setSchoolYear(schoolYear);
        subject.setTerm(term);
      return this.getQueryFactory().select(qMyLectureV.subjectId,
            qMyLectureV.count(),
            new CaseBuilder()
             .when(qMyLectureV.percent.gt(0.95)).then(1).otherwise(0).sum()).//大于95%算完成
            from(qMyLectureV).
            where(qMyLectureV.classId.eq(classId).and(qMyLectureV.id.userId.eq(ClientUtils.getUserId()))).
            groupBy(qMyLectureV.subjectId).fetch().stream()
             .map(tuple -> {
                Map<String,Object> map = new HashMap<String,Object>(3);
                map.put("subjectId", tuple.get(0, String.class));
                map.put("lectureCount",  tuple.get(1, Integer.class));
                map.put("completeLectureCount", tuple.get(2, String.class));
                return map;
             }).collect(Collectors.toList());
   }
   /**
    * 我的课程,按时间排序
    *
    * @param classId
    * @return
    */
   public List<Map<String,Object>> mySubjectList(String classId, Pager pager) {
      //课程
      List<Map<String,Object>> clsSubjectlist = this.myClsSubjectlist(classId, ClientUtils.getUserId(), pager);
      //课件统计
      List<Map<String,Object>> lectures = this.myLectureList(classId);
      for(Map<String,Object> clsSubject : clsSubjectlist) {
         String origSubjectId = (String)clsSubject.get("origSubjectId");
         clsSubject.put("exam", CollectionUtils.newObjectMap("examCount", this.examService.listStudentExamCount("", new String[] {classId}, origSubjectId, null)));
         clsSubject.put("homework", CollectionUtils.newObjectMap("homeworkCount", exerciseInfoService.queryStuExerciseListCount("", null, ClientUtils.getUserId(), origSubjectId, null)));
         clsSubject.put("lecture", CollectionUtils.newObjectMap("lectureCount", 0, "completeLectureCount", 0));
         clsSubject.put("mediaVideoLive", CollectionUtils.newObjectMap("mediaVideoLiveCount", this.mediaLiveService.listCount("", new String[] {classId}, origSubjectId, null)));
         this.setSubjectStatistics("lecture", clsSubject, lectures);
      }
      return clsSubjectlist;
   }
   /**
    * 统计课程的数据
    *
    * @param type 类型
    * @param clsSubject 课程
    * @param lstStatistics 统计信息
    */
   private void setSubjectStatistics(String type, Map<String,Object> clsSubject,  List<Map<String,Object>> lstStatistics) {
      if(lstStatistics != null && !lstStatistics.isEmpty()) {
         for(Map<String,Object> statistics : lstStatistics) {
            if(clsSubject.get("origSubjectId").equals(statistics.get("subjectId")) || clsSubject.get("subjectId").equals(statistics.get("subjectId"))) {
               clsSubject.put(type, statistics);
            }
         }
      }
   }
   /**
    * 我的课程详情
    *
    * @param classId
    * @return
    */
   public Map<String,Object> mySubjectInfo(String subjectId, String classId,HttpServletRequest request) {
      QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
      QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
      Object userId = request.getSession().getAttribute("userId");
      // 课程
      Tuple tuple = this.getQueryFactory()
            .select(qMySubjectV.id.subjectId, qMySubjectV.subjectName, qMySubjectV.term, qMySubjectV.schoolYear,qMySubjectV.origSubjectId,
                  qMySubjectV.percent,qMySubjectV.coverPageUrl, qMySubjectV.progressValue)
            .from(qMySubjectV)
            .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(ClientUtils.getUserId()))
                  .and(qMySubjectV.id.subjectId.eq(subjectId)))
            .fetchOne();
      Subject objSubject = this.read(subjectId);
        save(subject);
        return new Result(true, "success");
    }
      Map<String, Object> subject = new HashMap<String, Object>(5);
      subject.put("name", objSubject.getName());
      subject.put("subjectId", subjectId);
      subject.put("origSubjectId", objSubject.getOrigSubjectId());
      subject.put("schoolYear", objSubject.getSchoolYear());
      subject.put("term", objSubject.getTerm());
      subject.put("coverPageUrl", objSubject.getCoverPageUrl());
      subject.put("content", this.readSubjectContent(subjectId));
      subject.put("teacherName", objSubject.getTeacherName());
      if(tuple == null) {
         subject.put("progressPercent", 0);
         subject.put("progressValue", 0);
      }else {
         subject.put("progressPercent", tuple.get(qMySubjectV.percent));
         subject.put("progressValue", tuple.get(qMySubjectV.progressValue));
      }
    @Override
    public Result deleteClsSubject(String classId, String[] subjectIds) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("classId", classId);
        paramMap.put("subjectIds", subjectIds);
      String origSubjectId = objSubject.getOrigSubjectId();
      // 考试统计
      long examsCount = this.examService.listStudentExamCount("", new String[] {classId}, origSubjectId, null);
        List<String> reIdLst = this.findByComplexHql("select r.clsReSubjectId from ClsClassReSubject r where r.deleteFlag is false and r.classId=:classId and r.subjectId in (:subjectIds) ",
                paramMap, String.class);
      // 作业统计
      long homeworksCount = exerciseInfoService.queryStuExerciseListCount("", null, ClientUtils.getUserId(), origSubjectId, null);
        //删除关联关系
        if (reIdLst != null && reIdLst.size() > 0) {
            this.bulkUpdateInLoop("update ClsClassReSubject set deleteFlag = true where clsReSubjectId=?", reIdLst.toArray());
        }
      // 课件统计
      Tuple tupleLecture = this.getQueryFactory().select(qMyLectureV.count(),
            new CaseBuilder().when(qMyLectureV.percent.gt(0.95)).then(1).otherwise(0).sum()).// 大于95%算完成
            from(qMyLectureV)
            .where(qMyLectureV.classId.eq(classId).and(qMyLectureV.id.userId.eq(ClientUtils.getUserId()))
                  .and(qMyLectureV.subjectId.eq(subjectId)))
            .groupBy(qMyLectureV.subjectId).fetchOne();
        this.delete(subjectIds);
        return new Result(true, "success");
    }
      long mediaVideoLivesCount = this.mediaLiveService.listCount("", new String[] {classId}, origSubjectId, null);
    @Override
    public Result getPerformance4Subject() {
        String findCompleteCountByHql = "from MySubjectV where id.userId = ? and percent = 1 ";
        String findUndoneByHql = "from MySubjectV where id.userId = ? and (percent != 1 or percent is null)";
        String userId = ClientUtils.getUserId();
        int CompleteCount = findCount(findCompleteCountByHql, CollectionUtils.newList(userId));
        int UndoneCount = findCount(findUndoneByHql, CollectionUtils.newList(userId));
        return new Result(true, "success",
                CollectionUtils.newObjectMap("CompleteCount", CompleteCount, "UndoneCount", UndoneCount));
    }
      return CollectionUtils.newObjectMap("mediaVideoLivesCount", mediaVideoLivesCount, "examsCount", examsCount,
            "homeworksCount", homeworksCount, "subjectInfo", subject, "lectureCount",
            tupleLecture == null?0:tupleLecture.get(0, Long.class),
                  "completeLectureCount", tupleLecture == null?0:tupleLecture.get(1,Integer.class));
   }
   /**
    * 我的课程按学期分类
    *
    * @param classId
    * @return
    */
   @Override
   public List<Map<String,Object>> myTermSubjectList(String classId) {
      //课程
      List<Map<String,Object>> clsSubjectlist = this.mySubjectList(classId, new Pager());
      System.out.println("clsSubjectlistaaaaaa"+clsSubjectlist);
      return this.termSubjectList(classId, clsSubjectlist);
   }
    @Override
    public Result lstSubjectDetail() {
        String userId = ClientUtils.getUserId();
        StringBuffer hql = new StringBuffer(
                "select percent as percent,className as className ,id.classId as classId ,id.subjectId as subjectId ,"
                        + "subjectName as subjectName ,coverPageUrl as coverPageUrl , progressValue as progressValue from"
                        + " MySubjectV p where p.id.userId =:userId and p.subjectStatus=:subjectStatus ");
        Map<String, Object> args = CollectionUtils.newObjectMap("userId", userId, "subjectStatus", Subject.STATUS_ISSUED);
        List<Map<String, Object>> subjectLstMap = findListWithMapByHql(hql.toString(), args);
        for (Map<String, Object> subject : subjectLstMap) {
            String classId = (String) subject.get("classId");
            String subjectId = (String) subject.get("subjectId");
            Map<String, Object> map = progressDao.getStudyById(userId, subjectId, classId);
            List<MyLectureV> myLectureVList = lectureService.listLectureVBySubjectId(userId, subjectId, "", 1000, 1, null);
            Double percent = 0.0;
            Double progressValue = 0.0;
            Double percentAvg = 0.0;
            if (!myLectureVList.isEmpty()) {
                for (MyLectureV myLectureV : myLectureVList) {
                    if (myLectureV.getPercent() != null && myLectureV.getProgressValue() != null) {
                        percent += myLectureV.getPercent();
                        progressValue += myLectureV.getProgressValue().intValue();
                    }
                }
                percentAvg = percent / myLectureVList.size();
                if (percentAvg.isNaN()) {
                    percentAvg = 0.0;
                }
            }
            subject.put("percent", new BigDecimal(percentAvg));
            subject.put("progressValue", new BigDecimal(progressValue));
            subject.put("lectureParentId", map.get("lectureParentId"));
            subject.put("lectureId", map.get("lectureId"));
            subject.put("unCommitExerciseCount", exerciseInfoService.getUnCommitExerciseCount(classId, userId));
            subject.put("toBeCommitExerciseCount", exerciseInfoService.getToBeCommitExerciseCount(classId, userId));
            subject.put("CommitExerciseCount", exerciseInfoService.getCommitExerciseCount(classId, userId));
            subject.put("exerciseCount", exerciseInfoService.getExerciseCount(classId, userId));
            subject.put("examCount", examService.getExamCount(classId, userId));
            subject.put("unCommitExamCount", examService.getUnCommitExamCount(classId, userId));
            subject.put("commitExamCount", examService.getCommitExamCount(classId, userId));
            subject.put("toBeCommitExamCount", examService.getToBeCommitExamCount(classId, userId));
        }
        List<OpenSubjectV> subjects = listOpenSubjectV();
        for(OpenSubjectV subject : subjects){
            Map<String, Object> subjectMap = new HashMap<>();
            String classId = ClientUtils.getClassId();
            String subjectId =  subject.getSubjectId();
            Map<String, Object> map = progressDao.getStudyById(userId, subjectId, null);
            List<MyOpenLectureV> myLectureVList = lectureService.listOpenLectureVBySubjectId(userId, subjectId, "", 1000, 1, null);
            Double percent = 0.0;
            Double progressValue = 0.0;
            Double percentAvg = 0.0;
            if (!myLectureVList.isEmpty()) {
                for (MyOpenLectureV myOpenLectureV : myLectureVList) {
                    if (myOpenLectureV.getPercent() != null && myOpenLectureV.getProgressValue() != null) {
                        percent += myOpenLectureV.getPercent();
                        progressValue += myOpenLectureV.getProgressValue().intValue();
                    }
                }
                percentAvg = percent / myLectureVList.size();
                if (percentAvg.isNaN()) {
                    percentAvg = 0.0;
                }
            }
            String className = "公开课";
            subjectMap.put("subjectName",subject.getSubjectName());
            subjectMap.put("subjectId",subject.getSubjectId());
            subjectMap.put("coverPageUrl",subject.getCoverPageUrl());
            subjectMap.put("percent", new BigDecimal(percentAvg));
            subjectMap.put("progressValue", new BigDecimal(progressValue));
            subjectMap.put("className",className);
            subjectMap.put("lectureParentId", map.get("lectureParentId"));
            subjectMap.put("lectureId", map.get("lectureId"));
            subjectMap.put("unCommitExerciseCount", exerciseInfoService.getUnCommitExerciseCount(classId, userId));
            subjectMap.put("toBeCommitExerciseCount", exerciseInfoService.getToBeCommitExerciseCount(classId, userId));
            subjectMap.put("CommitExerciseCount", exerciseInfoService.getCommitExerciseCount(classId, userId));
            subjectMap.put("exerciseCount", exerciseInfoService.getExerciseCount(classId, userId));
            subjectMap.put("examCount", examService.getExamCount(classId, userId));
            subjectMap.put("unCommitExamCount", examService.getUnCommitExamCount(classId, userId));
            subjectMap.put("commitExamCount", examService.getCommitExamCount(classId, userId));
            subjectMap.put("toBeCommitExamCount", examService.getToBeCommitExamCount(classId, userId));
            subjectLstMap.add(subjectMap);
        }
        return new Result(true, "success", subjectLstMap);
    }
    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public Result getDataDesc(String classId, String subjectId) {
        if (StringUtils.isEmpty(classId)) {
            return new Result(false, "班级id参数错误");
        }
        QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
        List<Map<String, Object>> percentDesc = this.percentDesc(classId, subjectId, new OrderSpecifier(Order.DESC, qSubjectProgressTreeV.percent));
        List<Map<String, Object>> studyTimeDesc = this.percentDesc(classId, subjectId, new OrderSpecifier(Order.DESC, qSubjectProgressTreeV.progressValue));
        List<Map<String, Object>> exerciseInfoDesc = this.exerciseInfoDesc(classId, subjectId);
        List<Map<String, Object>> examInfoDesc = this.examInfoDesc(classId, subjectId);
        return new Result(true, "success", CollectionUtils.newObjectMap("percentDesc", percentDesc, "studyTimeDesc",
                studyTimeDesc, "exerciseInfoDesc", exerciseInfoDesc, "examInfoDesc", examInfoDesc));
    }
    /**
     * 获取班级对应的学员 按进度进行排序
     */
    private List<Map<String, Object>> percentDesc(String classId, String subjectId, @SuppressWarnings("rawtypes") OrderSpecifier order) {
        QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
        QUser qUser = QUser.user;
        String nodeId = StringUtils.isNotEmpty(subjectId) ? subjectId : classId;
        String nodeType = StringUtils.isNotEmpty(subjectId) ? Progress.PROGRESS_TYPE_SUBJECT : Progress.PROGRESS_TYPE_CLASS;
        List<Map<String, Object>> lstMap = this.getQueryFactory().select(qSubjectProgressTreeV.progressValue,
                qSubjectProgressTreeV.percent, qUser.name, qUser.userId, qSubjectProgressTreeV.id.nodeId).from(qSubjectProgressTreeV, qUser).
                where(qSubjectProgressTreeV.id.userId.eq(qUser.userId).and(qSubjectProgressTreeV.nodeType.eq(nodeType))
                        .and(qSubjectProgressTreeV.id.nodeId.eq(nodeId))).orderBy(order).fetch().stream().map(tuple -> {
            List<ClsClassReSubject> clsClassReSubjects = find("from ClsClassReSubject where classId = ?",CollectionUtils.newList(nodeId),ClsClassReSubject.class);
            int type = 3;
            List<Subject> subjects = find("from Subject where type = ?",CollectionUtils.newList(type),Subject.class);
            Double percent = 0.0;
            Double progressValue = 0.0;
            Double percentAvg = 0.0;
            int size = 0;
            for(ClsClassReSubject c : clsClassReSubjects) {
                List<MyLectureV> myLectureVList = lectureService.listLectureVBySubjectId(tuple.get(qUser.userId), c.getSubjectId(), "", 1000, 1, null);
                if (!myLectureVList.isEmpty()) {
                    for (MyLectureV myLectureV : myLectureVList) {
                        if (myLectureV.getPercent() != null && myLectureV.getProgressValue() != null) {
                            percent += myLectureV.getPercent();
                            progressValue += myLectureV.getProgressValue().intValue();
                        }
                    }
                    size += myLectureVList.size();
                    if (percentAvg.isNaN()) {
                        percentAvg += 0.0;
                    }
                }
            }
            for(Subject subject : subjects){
                List<MyOpenLectureV> myOpenLectureVList = lectureService.listOpenLectureVBySubjectId(tuple.get(qUser.userId), subject.getSubjectId(), "", 1000, 1, null);
                if(!myOpenLectureVList.isEmpty()){
                    for(MyOpenLectureV myOpenLecture : myOpenLectureVList){
                        if (myOpenLecture.getPercent() != null && myOpenLecture.getProgressValue() != null) {
                            percent += myOpenLecture.getPercent();
                            progressValue += myOpenLecture.getProgressValue().intValue();
                        }
                    }
                    size += myOpenLectureVList.size();
                    if (percentAvg.isNaN()) {
                        percentAvg += 0.0;
                    }
                }
            }
            percentAvg += percent / size;
            if(percentAvg.isNaN()){
                percentAvg = 0.0;
            }
            Map<String, Object> map = new HashMap<>();
            map.put("userName", tuple.get(qUser.name));
            map.put("userId", tuple.get(qUser.userId));
            map.put("classId", tuple.get(qSubjectProgressTreeV.id.nodeId));
            map.put("percent", percentAvg);
            map.put("progressValue", progressValue);
//            map.put("percent", tuple.get(qSubjectProgressTreeV.percent));
//            map.put("progressValue", tuple.get(qSubjectProgressTreeV.progressValue));
            return map;
        }).collect(Collectors.toList());
        return lstMap;
    }
    /**
     * 通过作业完成个数排序
     */
    private List<Map<String, Object>> exerciseInfoDesc(String classId, String subjectId) {
        QExerciseResultV qExerciseResultV = QExerciseResultV.exerciseResultV;
        //查询条件
        Predicate predicate = StringUtils.isEmpty(subjectId) ? qExerciseResultV.id.classId.eq(classId) :
                qExerciseResultV.id.classId.eq(classId).and(qExerciseResultV.subjectId.eq(subjectId));
        //case数量判断
        NumberExpression<BigDecimal> caseCount = new CaseBuilder()
                .when(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
                        .or(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
                .then(BigDecimal.ONE).otherwise(BigDecimal.ZERO).sum();
        //case分数
        NumberExpression<BigDecimal> caseScoreSum = new CaseBuilder()
                .when(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
                        .or(qExerciseResultV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
                .then(qExerciseResultV.score).otherwise(BigDecimal.ZERO).sum();
        List<Map<String, Object>> lstMap = this.getQueryFactory().select(qExerciseResultV.userId, qExerciseResultV.studentName,
                caseScoreSum.divide(caseCount), qExerciseResultV.count(), caseCount).from(qExerciseResultV).where(predicate).
                groupBy(qExerciseResultV.userId).
                orderBy(caseScoreSum.divide(caseCount).desc()).fetch().stream().map(tuple -> {
            Map<String, Object> map = new HashMap<>();
            map.put("userId", tuple.get(qExerciseResultV.userId));
            map.put("userName", tuple.get(qExerciseResultV.studentName));
            map.put("avgScore", tuple.get(2, BigDecimal.class));
            map.put("exerciseCount", tuple.get(3, BigDecimal.class));
            map.put("commitExerciseCount", tuple.get(4, BigDecimal.class));
            return map;
        }).collect(Collectors.toList());
        return lstMap;
    }
    /**
     *
     */
    private List<Map<String, Object>> examInfoDesc(String classId, String subjectId) {
        QExamResultV qExamResultV = QExamResultV.examResultV;
        //查询条件
        Predicate predicate = StringUtils.isEmpty(subjectId) ? qExamResultV.id.classId.eq(classId) :
                qExamResultV.id.classId.eq(classId).and(qExamResultV.subjectId.eq(subjectId));
        //case判断
        NumberExpression<BigDecimal> caseCount = new CaseBuilder()
                .when(qExamResultV.status.eq("0")).then(BigDecimal.ZERO).otherwise(BigDecimal.ONE).sum();
        //case分数
        NumberExpression<BigDecimal> caseScoreSum = new CaseBuilder()
                .when(qExamResultV.status.eq("0")).then(BigDecimal.ZERO).otherwise(qExamResultV.score).sum();
        List<Map<String, Object>> lstMap = this.getQueryFactory().select(qExamResultV.userId, qExamResultV.studentName,
                caseScoreSum.divide(caseCount), qExamResultV.count(), caseCount).from(qExamResultV).where(predicate).
                groupBy(qExamResultV.userId).
                orderBy(caseScoreSum.divide(caseCount).desc()).fetch().stream().map(tuple -> {
            Map<String, Object> map = new HashMap<>();
            map.put("userId", tuple.get(qExamResultV.userId));
            map.put("userName", tuple.get(qExamResultV.studentName));
            map.put("avgScore", tuple.get(2, BigDecimal.class));
            map.put("examCount", tuple.get(3, BigDecimal.class));
            map.put("commitExamCount", tuple.get(4, BigDecimal.class));
            return map;
        }).collect(Collectors.toList());
        return lstMap;
    }
    @Override
    public Result lastStudied(String userId) {
        Map<String, Object> map = progressDao.getStudyByUserId(userId);
        String subjectId = (String) map.get("subjectId");
        Subject subject = read(Subject.class, subjectId);
        if (subject != null) {
            map.put("subjectName", subject.getName());
        }
        return new Result(true, "success", map);
    }
    @Override
    public List<Map<String, Object>> queryAvailableSubjectIdAndName(String teacherId, Integer subjectType) {
        List<Map<String, Object>> result = null;
        if (subjectType == Subject.TYPE_PUBLIC_SUBJECT) {
            result = this.findListWithMapByHql(
                    "select subjectId as subjectId ,name as subjectName from Subject where deleteFlag is false and type=" + Subject.TYPE_PUBLIC_SUBJECT + " and orgId='" + ClientUtils.getOrgId() + "'", null);
        } else {
            if (StringUtils.isNotEmpty(teacherId)) {
                result = this.findListWithMapByHql(
//                        "select distinct origSubjectId as subjectId ,name as subjectName from Subject where deleteFlag is false and type=" + Subject.TYPE_CLS_SUBJECT + " and teacherId='" + teacherId + "'", null);
                        "select distinct origSubjectId as subjectId ,name as subjectName from Subject where deleteFlag is false and type=" + Subject.TYPE_ORG_SUBJECT + " and teacherId='" + teacherId + "'", null);
            } else {
                result = this.findListWithMapByHql(
                        "select subjectId as subjectId ,name as subjectName from Subject where deleteFlag is false and type=" + Subject.TYPE_ORG_SUBJECT + " and orgId='" + ClientUtils.getOrgId() + "'", null);
            }
        }
        return result;
    }
    @Override
    public List<Map<String, Object>> getMySubjectList() {
        String sql = "SELECT o.CLASS_ID, a.`NAME` AS subjectName, a.SUBJECT_ID, o.`NAME` AS className FROM ( ( SELECT "
                + "c.CLASS_ID, c.`NAME` FROM stu_student s, cls_class c WHERE s.CLASS_ID = c.CLASS_ID AND s.USER_ID =:userId"
                + " ) o LEFT JOIN ( SELECT r.class_id,s.SUBJECT_ID, s.`NAME` FROM `subject` s, cls_class_re_subject r WHERE "
                + "s.SUBJECT_ID = r.subject_id ) a ON o.CLASS_ID = a.class_id ) ";
        List<Object[]> list = findByComplexSql(sql, CollectionUtils.newObjectMap("userId", ClientUtils.getUserId()),
                Object[].class);
        List<Map<String, Object>> lstMap = new ArrayList<Map<String, Object>>(list.size());
        Map<String, Object> map = null;
        for (Object[] objects : list) {
            map = new HashMap<String, Object>(objects.length);
            map.put("classId", objects[0]);
            map.put("subjectName", objects[1]);
            map.put("subjectId", objects[2]);
            map.put("className", objects[3]);
            lstMap.add(map);
        }
        return lstMap;
    }
   /**
    * 课程按学期分类
    *
    * @param classId
    * @return
    */
   @Override
   public List<Map<String,Object>> termSubjectList(String classId, List<Map<String,Object>> clsSubjectlist) {
      //学期
      List<Map<String,Object>> termList = this.termList(classId);
      if(termList != null && !termList.isEmpty()) {
         for(Map<String,Object> term : termList) {
            if(termList != null && !termList.isEmpty()) {
               List<Map<String,Object>> subjectList = new ArrayList<>();
               for(Map<String,Object> clsSubject : clsSubjectlist) {
                  if(term.get("schoolYear").equals(clsSubject.get("schoolYear")) &&
                        term.get("term").equals(clsSubject.get("term"))) {
                     subjectList.add(clsSubject);
                  }
                  term.put("subjectList", subjectList);
               }
            }
         }
      }
      return termList;
   }
   /**
    * 查询课程关联的班级课程信息
    *
    * @param classId
    * @return
    */
   @Override
   public List<Map<String,Object>> querySubjectReClassInfos(String origSubjectId) {
      String hql = "select s.subjectId as subjectId ,s.teacherId as teacherId,s.teacherName as teacherName,"
              + " s.schoolYear as schoolYear,s.term as term,c.classId as classId,c.name as className"
              + " from Subject s ,ClsClassReSubject r ,ClsClass c where s.subjectId = r.subjectId "
              + " and r.classId = c.classId and s.origSubjectId =:origSubjectId and s.deleteFlag is false";
      return this.findListWithMapByHql(hql,CollectionUtils.newObjectMap("origSubjectId",origSubjectId));
   }
};
    @Override
    public List<Map<String, Object>> clsSubjectlist(String classId, Integer schoolYear, Integer term) {
        QSubject qSubject = QSubject.subject;
        QClsClassReSubject qClsClassReSubject = QClsClassReSubject.clsClassReSubject;
        QueryDslOptionBuilder builder = new QueryDslOptionBuilder().
                and(qSubject.deleteFlag::eq, false)
                .and(qClsClassReSubject.classId::eq, classId)
                .and(qClsClassReSubject.subjectId::eq, qSubject.subjectId)
                .and(qClsClassReSubject.deleteFlag::eq, false).and(qSubject.status::eq, Subject.STATUS_ISSUED);
        if (schoolYear != null && schoolYear != 0) {//学年
            builder = builder.and(qSubject.schoolYear::eq, schoolYear);
        }
        if (term != null && term != 0) {//学期
            builder = builder.and(qSubject.term::eq, term);
        }
        return this.getQueryFactory().select(qSubject.name, qSubject.origSubjectId, qSubject.subjectId, qSubject.schoolYear, qSubject.term).distinct()
                .from(qSubject, qClsClassReSubject)
                .where(builder.build())
                .orderBy(qSubject.createTime.desc())
                .fetch().stream()
                .map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(2);
                    map.put("name", tuple.get(qSubject.name));
                    map.put("subjectId", tuple.get(qSubject.subjectId));
                    map.put("schoolYear", tuple.get(qSubject.schoolYear));
                    map.put("term", tuple.get(qSubject.term));
                    map.put("origSubjectId", tuple.get(qSubject.origSubjectId));
                    return map;
                }).collect(Collectors.toList());
    }
    @Override
    public List<Map<String, Object>> termList(String classId) {
        QSubject qSubject = QSubject.subject;
        QClsClassReSubject qClsClassReSubject = QClsClassReSubject.clsClassReSubject;
        QueryDslOptionBuilder builder = new QueryDslOptionBuilder().
                and(qSubject.deleteFlag::eq, false)
                .and(qClsClassReSubject.classId::eq, classId)
                .and(qClsClassReSubject.subjectId::eq, qSubject.subjectId)
                .and(qClsClassReSubject.deleteFlag::eq, false).and(qSubject.status::eq, Subject.STATUS_ISSUED);
        return this.getQueryFactory().select(qSubject.schoolYear.as("schoolYear"), qSubject.term.as("term"))
                .from(qSubject, qClsClassReSubject)
                .where(builder.build().and(qSubject.schoolYear.isNotNull())
                        .and(qSubject.term.isNotNull())).groupBy(qSubject.schoolYear, qSubject.term)
                .orderBy(qSubject.schoolYear.desc(), qSubject.term.desc())
                .fetch().stream()
                .map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(2);
                    map.put("schoolYear", tuple.get(0, Integer.class));
                    map.put("term", tuple.get(1, Integer.class));
                    return map;
                }).collect(Collectors.toList());
    }
    /**
     * 我的班级信息
     *
     * @param classId
     * @return
     */
    public Map<String, Object> myClassInfo(String classId) {
        ClsClass objClsClass = this.read(ClsClass.class, classId);
        QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
        List<Subject> lstSubject = objClsClass.getSubjects();
        //过滤掉状态为草稿的
        List<String> teachers = lstSubject.stream().filter(u -> u.getStatus().equals(Subject.STATUS_ISSUED)).map(tuple -> {
            return tuple.getTeacherName();
        }).collect(Collectors.toList());
        SubjectProgressTreeV objSubjectProgressTreeV = this.getQueryFactory().selectFrom(qSubjectProgressTreeV)
                .where(qSubjectProgressTreeV.id.nodeId.eq(classId).and(qSubjectProgressTreeV.id.userId.eq(ClientUtils.getUserId())).and(qSubjectProgressTreeV.nodeType.eq("class"))).fetchOne();
        if (objSubjectProgressTreeV != null) {
            long allCount = this.getQueryFactory().selectFrom(qSubjectProgressTreeV)
                    .where(qSubjectProgressTreeV.id.nodeId.eq(classId)).fetchCount();
            long lgCount = this.getQueryFactory().selectFrom(qSubjectProgressTreeV)
                    .where(qSubjectProgressTreeV.id.nodeId.eq(classId).and(qSubjectProgressTreeV.percent.gt(objSubjectProgressTreeV.getPercent()))).fetchCount();
            //排行
            float rank = (allCount - lgCount) / allCount;
            return CollectionUtils.newObjectMap("className", objClsClass.getName(), "progressPercent",
                    objSubjectProgressTreeV.getPercent(), "progressValue", objSubjectProgressTreeV.getProgressValue(), "rank", rank, "teacherName", teachers);
        } else {
            return CollectionUtils.newObjectMap("className", objClsClass.getName(), "percent",
                    0, "progressValue", 0, "rank", 0, teachers);
        }
    }
    /**
     * 获取我的课程进度
     *
     * @param classId
     * @return
     */
    public List<Map<String, Object>> myClsSubjectlist(String classId, String userId, Pager pager) {
        String teacherId = this.teacherService.getTeacherIdByUserId(ClientUtils.getUserId());
        QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
        Predicate predicate = null;
        if (StringUtils.isNotEmpty(teacherId)) {
            predicate = qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(userId)).and(qMySubjectV.teacherId.eq(teacherId).and(qMySubjectV.subjectStatus.eq(Subject.STATUS_ISSUED)));
        } else {
            predicate = qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(userId).and(qMySubjectV.subjectStatus.eq(Subject.STATUS_ISSUED)));
        }
        return this.getQueryFactory().select(qMySubjectV.id.subjectId,
                qMySubjectV.subjectName, qMySubjectV.term,
                qMySubjectV.schoolYear, qMySubjectV.percent, qMySubjectV.coverPageUrl, qMySubjectV.origSubjectId)
                .from(qMySubjectV)
                .where(predicate)
                .orderBy(qMySubjectV.schoolYear.desc(), qMySubjectV.term.desc())
                .limit(pager.getPageSize()).offset(pager.getOffset())
                .fetch().stream()
                .map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(5);
                    map.put("name", tuple.get(qMySubjectV.subjectName));
                    map.put("origSubjectId", tuple.get(qMySubjectV.origSubjectId));
                    map.put("subjectId", tuple.get(qMySubjectV.id.subjectId));
                    map.put("progressPercent", tuple.get(qMySubjectV.percent));
                    map.put("schoolYear", tuple.get(qMySubjectV.schoolYear));
                    map.put("term", tuple.get(qMySubjectV.term));
                    map.put("coverPageUrl", tuple.get(qMySubjectV.coverPageUrl));
                    return map;
                }).collect(Collectors.toList());
    }
    /**
     * 获取我的课程数量
     *
     * @param classId
     * @return
     */
    public long myClsSubjectCount(String classId) {
        QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
        return this.getQueryFactory().select(qMySubjectV.id.subjectId,
                qMySubjectV.subjectName, qMySubjectV.term,
                qMySubjectV.schoolYear, qMySubjectV.percent)
                .from(qMySubjectV)
                .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(ClientUtils.getUserId())).and(qMySubjectV.subjectStatus.eq(Subject.STATUS_ISSUED)))
                .fetchCount();
    }
    /**
     * 获取学员的课程进度
     *
     * @param classId
     * @return
     */
    public List<Map<String, Object>> studentSubjectProgress(String classId, Pager pager) {
        String teacherId = this.teacherService.getTeacherIdByUserId(ClientUtils.getUserId());
        QSubjectProgressTreeV qSubjectProgressTreeV = QSubjectProgressTreeV.subjectProgressTreeV;
        QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
        return this.getQueryFactory().select(qMySubjectV.id.subjectId,
                qMySubjectV.subjectName, qMySubjectV.term, qMySubjectV.coverPageUrl,
                qMySubjectV.schoolYear, qMySubjectV.lectureCount, qMySubjectV.percent.avg().as(qMySubjectV.percent))
                .from(qMySubjectV)
                .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.teacherId.eq(teacherId)))
                .groupBy(qMySubjectV.id.subjectId)
                .orderBy(qMySubjectV.schoolYear.desc(), qMySubjectV.term.desc())
                .limit(pager.getPageSize()).offset(pager.getOffset())
                .fetch().stream()
                .map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(5);
                    map.put("name", tuple.get(qMySubjectV.subjectName));
                    map.put("subjectId", tuple.get(qMySubjectV.id.subjectId));
                    map.put("schoolYear", tuple.get(qMySubjectV.schoolYear));
                    map.put("term", tuple.get(qMySubjectV.term));
                    map.put("progressPercent",
                            this.getQueryFactory().select(qSubjectProgressTreeV.percent.avg())
                                    .from(qSubjectProgressTreeV)
                                    .where(qSubjectProgressTreeV.id.nodeId.eq(tuple.get(qMySubjectV.id.subjectId))
                                            .and(qSubjectProgressTreeV.nodeType.eq(Progress.PROGRESS_TYPE_SUBJECT)))
                                    .groupBy(qSubjectProgressTreeV.id.nodeId).fetchOne());
                    map.put("coverPageUrl", tuple.get(qMySubjectV.coverPageUrl));
                    map.put("lectureCount", this.getLectureCount(tuple.get(qMySubjectV.id.subjectId)));
                    return map;
                }).collect(Collectors.toList());
    }
    /**
     * 获取课件数量
     *
     * @param subjectId
     * @return
     */
    public long getLectureCount(String subjectId) {
        Subject subject = this.read(subjectId);
        if (subject == null) {
            return 0l;
        }
        if (subject.getType() == Subject.TYPE_CLS_SUBJECT) {//班级课程
            QClsSubjectLecture qSubjectLecture = QClsSubjectLecture.clsSubjectLecture;
            return this.getQueryFactory().selectFrom(qSubjectLecture).where(qSubjectLecture.deleteFlag.isFalse()
                    .and(qSubjectLecture.subjectId.eq(subjectId)).and(qSubjectLecture.status.eq(SubjectLecture.STATUS_DRAFT))).fetchCount();
        } else {
            QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
            return this.getQueryFactory().selectFrom(qSubjectLecture).where(qSubjectLecture.deleteFlag.isFalse()
                    .and(qSubjectLecture.subjectId.eq(subjectId)).and(qSubjectLecture.status.eq(SubjectLecture.STATUS_DRAFT))).fetchCount();
        }
    }
    @Override
    public String findSubjectName(String subjectId) {
        Subject subject = findUnique("from Subject where subjectId = ? ",CollectionUtils.newList(subjectId),Subject.class);
        return subject.getName();
    }
    /**
     * 我的公开课列表
     *
     * @param pageNum
     * @param pageSize
     * @param keyword
     * @return
     */
    public Map<String, Object> myOpenSubjectList(Integer pageNum, Integer pageSize, String keyword) {
        QSubject qSubject = QSubject.subject;
        QProgress qProgress = QProgress.progress;
        QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
        JPAQuery<Tuple> query = this.getQueryFactory()
                .select(qSubject.subjectId, qSubject.name, qSubject.term, qSubject.coverPageUrl, qSubject.schoolYear,
                        qProgress.progressPercent.avg().as(qProgress.progressPercent), qProgress.progressValue.sum().as(qProgress.progressValue))
                .from(qSubject, qProgress, qSubjectLecture)
                .where(qSubject.deleteFlag.isFalse().and(qSubjectLecture.subjectId.eq(qSubject.subjectId))
                        .and(qSubjectLecture.deleteFlag.isFalse()).and(qSubjectLecture.lectureId.eq(qProgress.targetId))
                        .and(qProgress.learnerId.eq(ClientUtils.getUserId()))
                        .and(qSubject.name.like("%" + keyword + "%").and(qProgress.deleteFlag.isFalse()))
                        .and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE)).and(qSubject.status.eq(Subject.STATUS_ISSUED))).groupBy(qSubject.subjectId);
        long count = query.fetchCount();
        List<Map<String, Object>> listData = query.orderBy(qProgress.createTime.desc()).limit(pageSize).offset(pageNum).fetch().stream().map(tuple -> {
            Map<String, Object> map = new HashMap<String, Object>(7);
            String subjectId = tuple.get(qSubject.subjectId);
            map.put("name", tuple.get(qSubject.name));
            map.put("subjectId", subjectId);
            map.put("schoolYear", tuple.get(qSubject.schoolYear));
            map.put("term", tuple.get(qSubject.term));
            map.put("coverPageUrl", tuple.get(qSubject.coverPageUrl));
            map.put("progressPercent", tuple.get(qProgress.progressPercent));
            map.put("progressValue", tuple.get(qProgress.progressValue));
            Map<String, Object> openSubjectDetail = this.openSubjectDetail(subjectId);
            // 直播数量
            map.put("mediaVideoLiveCount", openSubjectDetail.get("mediaVideoLiveCount"));
            // 课件数量
            map.put("subjectLectureCount", openSubjectDetail.get("subjectLectureCount"));
            //学习人次
            map.put("studyCount", openSubjectDetail.get("studyCount"));
            map.put("content", openSubjectDetail.get("content"));
            // 已观看完成课件数量
            map.put("subjectLectureDoCount", openSubjectDetail.get("subjectLectureDoCount"));
            return map;
        }).collect(Collectors.toList());
        return CollectionUtils.newObjectMap("count", count, "listData", listData);
    }
    /**
     * 课程统计详情
     *
     * @param subjectId
     * @return
     */
    public Map<String, Object> openSubjectDetail(String subjectId) {
        Map<String, Object> map = new HashMap<String, Object>();
        QMediaVideoLive qMediaVideoLive = QMediaVideoLive.mediaVideoLive;
        QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
        QProgress qProgress = QProgress.progress;
        // 直播数量
        map.put("mediaVideoLiveCount",
                this.getQueryFactory().select(qMediaVideoLive).from(qMediaVideoLive)
                        .where(qMediaVideoLive.deleteFlag.isFalse()
                                .and(qMediaVideoLive.status.gt(0))
                                .and(qMediaVideoLive.subjectId.eq(subjectId)))
                        .fetchCount());
        // 课件数量
        map.put("subjectLectureCount",
                this.getQueryFactory().select(qSubjectLecture).from(qSubjectLecture)
                        .where(qSubjectLecture.deleteFlag.isFalse()
                                .and(qSubjectLecture.subjectId.eq(subjectId)).and(qSubjectLecture.status.eq(SubjectLecture.STATUS_DRAFT)))
                        .fetchCount());
        //学习人次
        map.put("studyCount",
                this.getQueryFactory().selectDistinct(qProgress.learnerId).from(qProgress, qSubjectLecture)
                        .where(qProgress.deleteFlag.isFalse().and(qSubjectLecture.deleteFlag.isFalse()).and(qSubjectLecture.subjectId.eq(subjectId)).and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE))
                                .and(qProgress.targetId.eq(qSubjectLecture.lectureId)))
                        .fetchCount());
        map.put("content", this.readSubjectContent(subjectId));
        // 已观看完成课件数量
        map.put("subjectLectureDoCount",
                this.getQueryFactory().select(qSubjectLecture).from(qSubjectLecture, qProgress)
                        .where(qSubjectLecture.deleteFlag.isFalse().and(qProgress.deleteFlag.isFalse())
                                .and(qProgress.learnerId.eq(ClientUtils.getUserId())).and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE))
                                .and(qProgress.progressPercent.gt(0.95)).and(qProgress.targetId.eq(qSubjectLecture.lectureId))
                                .and(qSubjectLecture.subjectId.eq(subjectId)))
                        .fetchCount());
        return map;
    }
    /**
     * 公开课详情
     *
     * @param subjectId
     * @return
     */
    public Map<String, Object> openSubjectInfo(String subjectId) {
        QProgress qProgress = QProgress.progress;
        QSubjectLecture qSubjectLecture = QSubjectLecture.subjectLecture;
        Subject objSubject = this.read(subjectId);
        Tuple progress = this.getQueryFactory()
                .select(qProgress.progressPercent.sum().as(qProgress.progressPercent), qProgress.progressValue.sum().as(qProgress.progressValue)).from(qProgress, qSubjectLecture).where(qProgress.learnerId.eq(ClientUtils.getUserId())
                        .and(qProgress.targetId.eq(qSubjectLecture.lectureId))
                        .and(qProgress.deleteFlag.isFalse()).and(qSubjectLecture.deleteFlag.isFalse()).and(qSubjectLecture.subjectId.eq(subjectId))
                        .and(qProgress.type.eq(Progress.PROGRESS_TYPE_LECTURE))).fetchOne();
        Map<String, Object> subjectInfo = new HashMap<String, Object>(7);
        subjectInfo.put("name", objSubject.getName());
        subjectInfo.put("subjectId", subjectId);
        subjectInfo.put("schoolYear", objSubject.getSchoolYear());
        subjectInfo.put("term", objSubject.getTerm());
        subjectInfo.put("coverPageUrl", objSubject.getCoverPageUrl());
        subjectInfo.put("teacherName", objSubject.getTeacherName());
        Map<String, Object> openSubjectDetail = this.openSubjectDetail(subjectId);
        Map<String, Object> map = new HashMap<String, Object>(7);
        // 直播数量
        map.put("mediaVideoLiveCount", openSubjectDetail.get("mediaVideoLiveCount"));
        // 课件数量
        map.put("subjectLectureCount", openSubjectDetail.get("subjectLectureCount"));
        //学习人次
        map.put("studyCount", openSubjectDetail.get("studyCount"));
        subjectInfo.put("content", openSubjectDetail.get("content"));
        // 已观看完成课件数量
        map.put("subjectLectureDoCount", openSubjectDetail.get("subjectLectureDoCount"));
        map.put("subjectInfo", subjectInfo);
        if (openSubjectDetail.get("subjectLectureCount") == null || progress == null || progress.get(qProgress.progressPercent) == null) {
            subjectInfo.put("progressPercent", 0);
        } else {
            subjectInfo.put("progressPercent", progress.get(qProgress.progressPercent).floatValue() / (Long) openSubjectDetail.get("subjectLectureCount"));
        }
        subjectInfo.put("progressValue", progress == null ? 0 : progress.get(qProgress.progressValue));
        return map;
    }
    @Override
    public Map<String, Object> mySubjectInfo(String subjectId, String classId) {
        QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
        QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
        // 课程
        Tuple tuple = this.getQueryFactory()
                .select(qMySubjectV.id.subjectId, qMySubjectV.subjectName, qMySubjectV.term, qMySubjectV.schoolYear, qMySubjectV.origSubjectId,
                        qMySubjectV.percent, qMySubjectV.coverPageUrl, qMySubjectV.progressValue)
                .from(qMySubjectV)
                .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(ClientUtils.getUserId()))
                        .and(qMySubjectV.id.subjectId.eq(subjectId)))
                .fetchOne();
        Subject objSubject = this.read(subjectId);
        Map<String, Object> subject = new HashMap<String, Object>(5);
        subject.put("name", objSubject.getName());
        subject.put("subjectId", subjectId);
        subject.put("origSubjectId", objSubject.getOrigSubjectId());
        subject.put("schoolYear", objSubject.getSchoolYear());
        subject.put("term", objSubject.getTerm());
        subject.put("coverPageUrl", objSubject.getCoverPageUrl());
        subject.put("content", this.readSubjectContent(subjectId));
        subject.put("teacherName", objSubject.getTeacherName());
        if (tuple == null) {
            subject.put("progressPercent", 0);
            subject.put("progressValue", 0);
        } else {
            subject.put("progressPercent", tuple.get(qMySubjectV.percent));
            subject.put("progressValue", tuple.get(qMySubjectV.progressValue));
        }
        String origSubjectId = objSubject.getOrigSubjectId();
        // 考试统计
        long examsCount = this.examService.listStudentExamCount("", new String[]{classId}, origSubjectId, null);
        // 作业统计
        long homeworksCount = exerciseInfoService.queryStuExerciseListCount("", null, ClientUtils.getUserId(), origSubjectId, null);
        // 课件统计
        Tuple tupleLecture = this.getQueryFactory().select(qMyLectureV.count(),
                new CaseBuilder().when(qMyLectureV.percent.gt(0.95)).then(1).otherwise(0).sum()).// 大于95%算完成
                from(qMyLectureV)
                .where(qMyLectureV.classId.eq(classId).and(qMyLectureV.id.userId.eq(ClientUtils.getUserId()))
                        .and(qMyLectureV.subjectId.eq(subjectId)))
                .groupBy(qMyLectureV.subjectId).fetchOne();
        long mediaVideoLivesCount = this.mediaLiveService.listCount("", new String[]{classId}, origSubjectId, null);
        return CollectionUtils.newObjectMap("mediaVideoLivesCount", mediaVideoLivesCount, "examsCount", examsCount,
                "homeworksCount", homeworksCount, "subjectInfo", subject, "lectureCount",
                tupleLecture == null ? 0 : tupleLecture.get(0, Long.class),
                "completeLectureCount", tupleLecture == null ? 0 : tupleLecture.get(1, Integer.class));
    }
    /**
     * 公开课列表
     *
     * @param pageNum
     * @param pageSize
     * @param keyword
     * @return
     */
    public Map<String, Object> openSubjectList(Integer pageNum, Integer pageSize, String keyword) {
        QOpenSubjectV qOpenSubjectV = QOpenSubjectV.openSubjectV;
        JPAQuery<OpenSubjectV> query = this.getQueryFactory().selectFrom(qOpenSubjectV).where(qOpenSubjectV.subjectName.like("%" + keyword + "%"));
        long count = query.fetchCount();
        List<Map<String, Object>> listData = query.orderBy(qOpenSubjectV.mediaVideoCount.desc(),
                qOpenSubjectV.learnerCount.desc(), qOpenSubjectV.createTime.desc()).limit(pageSize).offset(pageNum)
                .fetch().stream().map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(8);
                    map.put("name", tuple.getSubjectName());
                    map.put("subjectId", tuple.getSubjectId());
                    map.put("schoolYear", tuple.getSchoolYear());
                    map.put("term", tuple.getTerm());
                    map.put("coverPageUrl", tuple.getCoverPageUrl());
                    map.put("mediaVideoCount", tuple.getMediaVideoCount());
                    map.put("learnerCount", tuple.getLearnerCount());
                    map.put("createTime", tuple.getCreateTime());
                    return map;
                }).collect(Collectors.toList());
        return CollectionUtils.newObjectMap("count", count, "listData", listData);
    }
    /**
     * 班级学员课件总体进度
     *
     * @param subjectId
     * @param classId
     * @return
     */
    @Override
    public List<Map<String, Object>> studentSubjectLectureProgress(String subjectId, String classId) {
        QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
        return this.getQueryFactory()
                .select(qMyLectureV.lectureName, qMyLectureV.id.lectureId, qMyLectureV.lectureType,
                        qMyLectureV.chapterId, qMyLectureV.subjectId, qMyLectureV.lectureCreateTime,
                        qMyLectureV.percent.avg().as(qMyLectureV.percent))
                .from(qMyLectureV).where(qMyLectureV.classId.eq(classId).and(qMyLectureV.subjectId.eq(subjectId)))
                .groupBy(qMyLectureV.id.lectureId).orderBy(qMyLectureV.lectureCreateTime.desc()).fetch().stream()
                .map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(6);
                    map.put("lectureName", tuple.get(qMyLectureV.lectureName));
                    map.put("lectureId", tuple.get(qMyLectureV.id.lectureId));
                    map.put("lectureType", tuple.get(qMyLectureV.lectureType));
                    map.put("chapterId", tuple.get(qMyLectureV.chapterId));
                    map.put("subjectId", tuple.get(qMyLectureV.subjectId));
                    map.put("progressPercent", tuple.get(qMyLectureV.percent));
                    map.put("createTime", tuple.get(qMyLectureV.lectureCreateTime));
                    return map;
                }).collect(Collectors.toList());
    }
    /**
     * 学员课程作业进度
     *
     * @param classId
     * @param subjectId
     * @return
     */
    public Map<String, Object> studentSubjectHomeworkProgress(String classId, String subjectId, String studentId) {
        QExerciseResultV qHomeworkScoreV = QExerciseResultV.exerciseResultV;
        StuStudent student = read(StuStudent.class, studentId);
        Subject subject = read(Subject.class, subjectId);
        Tuple tuple = this.getQueryFactory()
                .select(qHomeworkScoreV.subjectId, qHomeworkScoreV.count(),
                        new CaseBuilder()
                                .when(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
                                        .or(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
                                .then(qHomeworkScoreV.studentScore).otherwise(BigDecimal.ZERO).sum(),
                        new CaseBuilder()
                                .when(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_CHECKED)
                                        .or(qHomeworkScoreV.completeStatus.eq(ExerciseCompleteInfo.STATUS_COMMIT)))
                                .then(1).otherwise(0).sum())
                .from(qHomeworkScoreV)
                .where(qHomeworkScoreV.subjectId.eq(subject.getOrigSubjectId())
                        .and(qHomeworkScoreV.userId.eq(student.getUserId()))
                        .and(qHomeworkScoreV.exerciseStatus.eq(ExerciseInfo.EXERCISE_STATUS_PUBLISHED)))
                .groupBy(qHomeworkScoreV.userId).fetchOne();
        Map<String, Object> map = new HashMap<String, Object>(4);
        if (tuple == null) {
            map.put("subjectId", subjectId);
            map.put("homeworkCount", 0);
            map.put("avgScore", "0");
            map.put("commitHomeworkCount", 0);
        } else {
            int commitHomeworkCount = tuple.get(3, Integer.class) == null ? 0 : tuple.get(3, Integer.class);
            map.put("subjectId", subjectId);
            map.put("homeworkCount", tuple.get(1, Integer.class) == null ? 0 : tuple.get(1, Integer.class));
            map.put("avgScore", String.valueOf(commitHomeworkCount == 0 || tuple.get(2, BigDecimal.class) == null ? BigDecimal.ZERO : tuple.get(2, BigDecimal.class).divide(BigDecimal.valueOf(commitHomeworkCount), 2, BigDecimal.ROUND_HALF_UP)));
            map.put("commitHomeworkCount", commitHomeworkCount);
        }
        return map;
    }
    /**
     * 学员考试作业进度
     *
     * @param classId
     * @param subjectId
     * @return
     */
    public Map<String, Object> studentSubjectExamProgress(String classId, String subjectId, String studentId) {
        QExamResultV qExamScoreV = QExamResultV.examResultV;
        StuStudent student = read(StuStudent.class, studentId);
        Subject subject = read(Subject.class, subjectId);
        Tuple tuple = this.getQueryFactory().select(qExamScoreV.subjectId, qExamScoreV.count(), new CaseBuilder()
                .when(qExamScoreV.status.eq("0")).then(BigDecimal.ZERO).otherwise(qExamScoreV.score).sum(), new CaseBuilder()
                .when(qExamScoreV.status.eq("0")).then(0).otherwise(1).sum()).
                from(qExamScoreV).
                where(qExamScoreV.subjectId.eq(subject.getOrigSubjectId()).and(qExamScoreV.userId.eq(student.getUserId())).and(qExamScoreV.examStatus.eq(ExerciseInfo.EXERCISE_STATUS_PUBLISHED))).
                groupBy(qExamScoreV.userId).fetchOne();
        Map<String, Object> map = new HashMap<String, Object>(4);
        map.put("subjectId", subjectId);
        if (tuple == null) {
            map.put("examCount", 0);
            map.put("avgScore", "0");
            map.put("commitExamCount", 0);
        } else {
            int commitExamCount = tuple.get(3, Integer.class) == null ? 0 : tuple.get(3, Integer.class);
            map.put("examCount", tuple.get(1, Integer.class) == null ? 0 : tuple.get(1, Integer.class));
            map.put("avgScore", String.valueOf(commitExamCount == 0 || tuple.get(2, BigDecimal.class) == null ? BigDecimal.ZERO : tuple.get(2, BigDecimal.class).divide(new BigDecimal(commitExamCount), 2, BigDecimal.ROUND_HALF_UP)));
            map.put("commitExamCount", tuple.get(3, Integer.class) == null ? 0 : tuple.get(3, Integer.class));
        }
        return map;
    }
    /**
     * 我的课件情况
     *
     * @param classId
     * @return
     */
    private List<Map<String, Object>> myLectureList(String classId) {
        QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
        return this.getQueryFactory().select(qMyLectureV.subjectId,
                qMyLectureV.count(),
                new CaseBuilder()
                        .when(qMyLectureV.percent.gt(0.95)).then(1).otherwise(0).sum()).//大于95%算完成
                from(qMyLectureV).
                where(qMyLectureV.classId.eq(classId).and(qMyLectureV.id.userId.eq(ClientUtils.getUserId()))).
                groupBy(qMyLectureV.subjectId).fetch().stream()
                .map(tuple -> {
                    Map<String, Object> map = new HashMap<String, Object>(3);
                    map.put("subjectId", tuple.get(0, String.class));
                    map.put("lectureCount", tuple.get(1, Integer.class));
                    map.put("completeLectureCount", tuple.get(2, String.class));
                    return map;
                }).collect(Collectors.toList());
    }
    /**
     * 我的课程,按时间排序
     *
     * @param classId
     * @return
     */
    public List<Map<String, Object>> mySubjectList(String classId, Pager pager) {
        //课程
        List<Map<String, Object>> clsSubjectlist = this.myClsSubjectlist(classId, ClientUtils.getUserId(), pager);
        //课件统计
        List<Map<String, Object>> lectures = this.myLectureList(classId);
        for (Map<String, Object> clsSubject : clsSubjectlist) {
            String origSubjectId = (String) clsSubject.get("origSubjectId");
            clsSubject.put("exam", CollectionUtils.newObjectMap("examCount", this.examService.listStudentExamCount("", new String[]{classId}, origSubjectId, null)));
            clsSubject.put("homework", CollectionUtils.newObjectMap("homeworkCount", exerciseInfoService.queryStuExerciseListCount("", null, ClientUtils.getUserId(), origSubjectId, null)));
            clsSubject.put("lecture", CollectionUtils.newObjectMap("lectureCount", 0, "completeLectureCount", 0));
            clsSubject.put("mediaVideoLive", CollectionUtils.newObjectMap("mediaVideoLiveCount", this.mediaLiveService.listCount("", new String[]{classId}, origSubjectId, null)));
            this.setSubjectStatistics("lecture", clsSubject, lectures);
        }
        return clsSubjectlist;
    }
    /**
     * 统计课程的数据
     *
     * @param type          类型
     * @param clsSubject    课程
     * @param lstStatistics 统计信息
     */
    private void setSubjectStatistics(String type, Map<String, Object> clsSubject, List<Map<String, Object>> lstStatistics) {
        if (lstStatistics != null && !lstStatistics.isEmpty()) {
            for (Map<String, Object> statistics : lstStatistics) {
                if (clsSubject.get("origSubjectId").equals(statistics.get("subjectId")) || clsSubject.get("subjectId").equals(statistics.get("subjectId"))) {
                    clsSubject.put(type, statistics);
                }
            }
        }
    }
    /**
     * 我的课程详情
     *
     * @param classId
     * @return
     */
    public Map<String, Object> mySubjectInfo(String subjectId, String classId, HttpServletRequest request) {
        QMySubjectV qMySubjectV = QMySubjectV.mySubjectV;
        QMyLectureV qMyLectureV = QMyLectureV.myLectureV;
        Object userId = request.getSession().getAttribute("userId");
        // 课程
        Tuple tuple = this.getQueryFactory()
                .select(qMySubjectV.id.subjectId, qMySubjectV.subjectName, qMySubjectV.term, qMySubjectV.schoolYear, qMySubjectV.origSubjectId,
                        qMySubjectV.percent, qMySubjectV.coverPageUrl, qMySubjectV.progressValue)
                .from(qMySubjectV)
                .where(qMySubjectV.id.classId.eq(classId).and(qMySubjectV.id.userId.eq(ClientUtils.getUserId()))
                        .and(qMySubjectV.id.subjectId.eq(subjectId)))
                .fetchOne();
        Subject objSubject = this.read(subjectId);
        Map<String, Object> subject = new HashMap<String, Object>(5);
        subject.put("name", objSubject.getName());
        subject.put("subjectId", subjectId);
        subject.put("origSubjectId", objSubject.getOrigSubjectId());
        subject.put("schoolYear", objSubject.getSchoolYear());
        subject.put("term", objSubject.getTerm());
        subject.put("coverPageUrl", objSubject.getCoverPageUrl());
        subject.put("content", this.readSubjectContent(subjectId));
        subject.put("teacherName", objSubject.getTeacherName());
        if (tuple == null) {
            subject.put("progressPercent", 0);
            subject.put("progressValue", 0);
        } else {
            subject.put("progressPercent", tuple.get(qMySubjectV.percent));
            subject.put("progressValue", tuple.get(qMySubjectV.progressValue));
        }
        String origSubjectId = objSubject.getOrigSubjectId();
        // 考试统计
        long examsCount = this.examService.listStudentExamCount("", new String[]{classId}, origSubjectId, null);
        // 作业统计
        long homeworksCount = exerciseInfoService.queryStuExerciseListCount("", null, ClientUtils.getUserId(), origSubjectId, null);
        // 课件统计
        Tuple tupleLecture = this.getQueryFactory().select(qMyLectureV.count(),
                new CaseBuilder().when(qMyLectureV.percent.gt(0.95)).then(1).otherwise(0).sum()).// 大于95%算完成
                from(qMyLectureV)
                .where(qMyLectureV.classId.eq(classId).and(qMyLectureV.id.userId.eq(ClientUtils.getUserId()))
                        .and(qMyLectureV.subjectId.eq(subjectId)))
                .groupBy(qMyLectureV.subjectId).fetchOne();
        long mediaVideoLivesCount = this.mediaLiveService.listCount("", new String[]{classId}, origSubjectId, null);
        return CollectionUtils.newObjectMap("mediaVideoLivesCount", mediaVideoLivesCount, "examsCount", examsCount,
                "homeworksCount", homeworksCount, "subjectInfo", subject, "lectureCount",
                tupleLecture == null ? 0 : tupleLecture.get(0, Long.class),
                "completeLectureCount", tupleLecture == null ? 0 : tupleLecture.get(1, Integer.class));
    }
    /**
     * 我的课程按学期分类
     *
     * @param classId
     * @return
     */
    @Override
    public List<Map<String, Object>> myTermSubjectList(String classId) {
        //课程
        List<Map<String, Object>> clsSubjectlist = this.mySubjectList(classId, new Pager());
        System.out.println("clsSubjectlistaaaaaa" + clsSubjectlist);
        return this.termSubjectList(classId, clsSubjectlist);
    }
    /**
     * 课程按学期分类
     *
     * @param classId
     * @return
     */
    @Override
    public List<Map<String, Object>> termSubjectList(String classId, List<Map<String, Object>> clsSubjectlist) {
        //学期
        List<Map<String, Object>> termList = this.termList(classId);
        if (termList != null && !termList.isEmpty()) {
            for (Map<String, Object> term : termList) {
                if (termList != null && !termList.isEmpty()) {
                    List<Map<String, Object>> subjectList = new ArrayList<>();
                    for (Map<String, Object> clsSubject : clsSubjectlist) {
                        if (term.get("schoolYear").equals(clsSubject.get("schoolYear")) &&
                                term.get("term").equals(clsSubject.get("term"))) {
                            subjectList.add(clsSubject);
                        }
                        term.put("subjectList", subjectList);
                    }
                }
            }
        }
        return termList;
    }
    /**
     * 查询课程关联的班级课程信息
     *
     * @param classId
     * @return
     */
    @Override
    public List<Map<String, Object>> querySubjectReClassInfos(String origSubjectId) {
        String hql = "select s.subjectId as subjectId ,s.teacherId as teacherId,s.teacherName as teacherName,"
                + " s.schoolYear as schoolYear,s.term as term,c.classId as classId,c.name as className"
                + " from Subject s ,ClsClassReSubject r ,ClsClass c where s.subjectId = r.subjectId "
                + " and r.classId = c.classId and s.origSubjectId =:origSubjectId and s.deleteFlag is false";
        return this.findListWithMapByHql(hql, CollectionUtils.newObjectMap("origSubjectId", origSubjectId));
    }
};