UCSBGradeHistoryServiceImpl.java

  1. package edu.ucsb.cs156.courses.services;

  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import com.opencsv.CSVReader;
  4. import edu.ucsb.cs156.courses.entities.GradeHistory;
  5. import edu.ucsb.cs156.courses.models.ApiResult;
  6. import edu.ucsb.cs156.courses.models.Quarter;
  7. import edu.ucsb.cs156.courses.models.TreeElement;
  8. import java.io.Reader;
  9. import java.io.StringReader;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.stream.Collectors;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.boot.web.client.RestTemplateBuilder;
  17. import org.springframework.http.HttpEntity;
  18. import org.springframework.http.HttpHeaders;
  19. import org.springframework.http.HttpMethod;
  20. import org.springframework.http.MediaType;
  21. import org.springframework.http.ResponseEntity;
  22. import org.springframework.stereotype.Service;
  23. import org.springframework.web.client.RestTemplate;

  24. @Service("UCSBGradeHistoryService")
  25. @Slf4j
  26. public class UCSBGradeHistoryServiceImpl implements UCSBGradeHistoryService {

  27.   private final RestTemplate restTemplate;

  28.   public UCSBGradeHistoryServiceImpl(RestTemplateBuilder restTemplateBuilder) {
  29.     restTemplate = restTemplateBuilder.build();
  30.   }

  31.   @Autowired ObjectMapper mapper;

  32.   public static final String REPO_OWNER_AND_NAME = "ucsb-cs156/UCSB_Grades";
  33.   public static final String API_ENDPOINT =
  34.       "https://api.github.com/repos/" + REPO_OWNER_AND_NAME + "/git/trees/main?recursive=1";

  35.   @Override
  36.   public List<String> getUrls() throws Exception {

  37.     log.info("getting data from {}", API_ENDPOINT);

  38.     HttpHeaders headers = new HttpHeaders();
  39.     headers.setAccept(List.of(MediaType.APPLICATION_JSON));
  40.     headers.setContentType(MediaType.APPLICATION_JSON);

  41.     HttpEntity<String> entity = new HttpEntity<>(headers);
  42.     Map<String, String> uriVariables = Map.of("recursive", "1");

  43.     ResponseEntity<String> re =
  44.         restTemplate.exchange(API_ENDPOINT, HttpMethod.GET, entity, String.class, uriVariables);

  45.     ApiResult apiResult = mapper.readValue(re.getBody(), ApiResult.class);

  46.     List<TreeElement> treeElements = apiResult.getTree();
  47.     List<String> urls =
  48.         treeElements.stream()
  49.             .map(treeElement -> treeElement.getPath())
  50.             .filter(path -> (path.startsWith("quarters/") && path.endsWith(".csv")))
  51.             .collect(Collectors.toList());
  52.     List<String> rawUrls =
  53.         urls.stream()
  54.             .map(url -> "https://raw.githubusercontent.com/" + REPO_OWNER_AND_NAME + "/main/" + url)
  55.             .collect(Collectors.toList());
  56.     return rawUrls;
  57.   }

  58.   @Override
  59.   public List<GradeHistory> getGradeData(String url) throws Exception {
  60.     log.info("getting data from {}", url);
  61.     HttpHeaders headers = new HttpHeaders();
  62.     headers.setAccept(List.of(MediaType.APPLICATION_JSON));
  63.     headers.setContentType(MediaType.APPLICATION_JSON);

  64.     HttpEntity<String> entity = new HttpEntity<>(headers);
  65.     ResponseEntity<String> re = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
  66.     String csvData = re.getBody();
  67.     return parse(new StringReader(csvData));
  68.   }

  69.   @Override
  70.   public List<GradeHistory> parse(Reader reader) throws Exception {
  71.     List<GradeHistory> gradeHistoryList = new ArrayList<GradeHistory>();
  72.     log.info("Parsing CSV file with grade history... ");
  73.     CSVReader csvReader = new CSVReader(reader);
  74.     csvReader.skip(1);
  75.     List<String[]> myEntries = csvReader.readAll();
  76.     for (String[] row : myEntries) {
  77.       String yyyyq = Integer.toString(Quarter.qyyToyyyyQ(row[0]));
  78.       GradeHistory gradeHistory =
  79.           GradeHistory.builder()
  80.               .yyyyq(yyyyq)
  81.               .course(row[2])
  82.               .instructor(row[3])
  83.               .grade(row[4])
  84.               .count(Integer.parseInt(row[5]))
  85.               .build();
  86.       log.info("Parsed: " + gradeHistory.toString());
  87.       gradeHistoryList.add(gradeHistory);
  88.     }
  89.     csvReader.close();
  90.     return gradeHistoryList;
  91.   }
  92. }