use of ai.elimu.model.contributor.AudioContributionEvent in project webapp by elimu-ai.
the class AudioPeerReviewsRestController method listWordRecordingsPendingPeerReview.
/**
* Get {@link AudioContributionEvent}s pending a {@link AudioPeerReviewEvent} for the current {@link Contributor}.
*/
@RequestMapping(value = "/words", method = RequestMethod.GET)
public String listWordRecordingsPendingPeerReview(HttpServletRequest request, HttpServletResponse response) {
logger.info("listWordRecordingsPendingPeerReview");
JSONObject jsonObject = new JSONObject();
// Lookup the Contributor by ID
String providerIdGoogle = request.getHeader("providerIdGoogle");
logger.info("providerIdGoogle: " + providerIdGoogle);
if (StringUtils.isBlank(providerIdGoogle)) {
jsonObject.put("result", "error");
jsonObject.put("errorMessage", "Missing providerIdGoogle");
response.setStatus(HttpStatus.BAD_REQUEST.value());
String jsonResponse = jsonObject.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
Contributor contributor = contributorDao.readByProviderIdGoogle(providerIdGoogle);
logger.info("contributor: " + contributor);
if (contributor == null) {
jsonObject.put("result", "error");
jsonObject.put("errorMessage", "The Contributor was not found.");
response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value());
String jsonResponse = jsonObject.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
List<AudioContributionEvent> allAudioContributionEvents = audioContributionEventDao.readAll();
logger.info("allAudioContributionEvents.size(): " + allAudioContributionEvents.size());
// Get the most recent AudioContributionEvent for each Audio
List<AudioContributionEvent> mostRecentAudioContributionEvents = new ArrayList<>();
HashMap<Long, Void> idsOfAudiosWithContributionEventHashMap = new HashMap<>();
for (AudioContributionEvent audioContributionEvent : allAudioContributionEvents) {
// Ignore AudioContributionEvent if one has already been added for this Audio
if (idsOfAudiosWithContributionEventHashMap.containsKey(audioContributionEvent.getAudio().getId())) {
continue;
}
// Keep track of the Audio ID
idsOfAudiosWithContributionEventHashMap.put(audioContributionEvent.getAudio().getId(), null);
// Ignore AudioContributionEvents made by the current Contributor
if (audioContributionEvent.getContributor().getId().equals(contributor.getId())) {
continue;
}
mostRecentAudioContributionEvents.add(audioContributionEvent);
}
logger.info("mostRecentAudioContributionEvents.size(): " + mostRecentAudioContributionEvents.size());
// For each AudioContributionEvent, check if the Contributor has already performed a peer review.
// If not, add it to the list of pending peer reviews.
List<AudioContributionEvent> audioContributionEventsPendingPeerReview = new ArrayList<>();
for (AudioContributionEvent mostRecentAudioContributionEvent : mostRecentAudioContributionEvents) {
AudioPeerReviewEvent audioPeerReviewEvent = audioPeerReviewEventDao.read(mostRecentAudioContributionEvent, contributor);
if (audioPeerReviewEvent == null) {
audioContributionEventsPendingPeerReview.add(mostRecentAudioContributionEvent);
}
}
logger.info("audioContributionEventsPendingPeerReview.size(): " + audioContributionEventsPendingPeerReview.size());
// Convert to JSON
JSONArray audioContributionEventsJsonArray = new JSONArray();
for (AudioContributionEvent audioContributionEvent : audioContributionEventsPendingPeerReview) {
AudioContributionEventGson audioContributionEventGson = JpaToGsonConverter.getAudioContributionEventGson(audioContributionEvent);
String json = new Gson().toJson(audioContributionEventGson);
audioContributionEventsJsonArray.put(new JSONObject(json));
}
String jsonResponse = audioContributionEventsJsonArray.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
use of ai.elimu.model.contributor.AudioContributionEvent in project webapp by elimu-ai.
the class AudioContributionsRestController method handleUploadWordRecordingRequest.
@RequestMapping(value = "/words", method = RequestMethod.POST)
public String handleUploadWordRecordingRequest(HttpServletRequest request, HttpServletResponse response, @RequestParam("file") MultipartFile multipartFile) {
logger.info("handleUploadWordRecordingRequest");
JSONObject jsonObject = new JSONObject();
String providerIdGoogle = request.getHeader("providerIdGoogle");
logger.info("providerIdGoogle: " + providerIdGoogle);
if (StringUtils.isBlank(providerIdGoogle)) {
jsonObject.put("result", "error");
jsonObject.put("errorMessage", "Missing providerIdGoogle");
response.setStatus(HttpStatus.BAD_REQUEST.value());
String jsonResponse = jsonObject.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
String timeSpentMsAsString = request.getHeader("timeSpentMs");
logger.info("timeSpentMsAsString: " + timeSpentMsAsString);
if (StringUtils.isBlank(timeSpentMsAsString)) {
jsonObject.put("result", "error");
jsonObject.put("errorMessage", "Missing timeSpentMs");
response.setStatus(HttpStatus.BAD_REQUEST.value());
String jsonResponse = jsonObject.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
Long timeSpentMs = Long.valueOf(timeSpentMsAsString);
// Lookup the Contributor by ID
Contributor contributor = contributorDao.readByProviderIdGoogle(providerIdGoogle);
logger.info("contributor: " + contributor);
if (contributor == null) {
jsonObject.put("result", "error");
jsonObject.put("errorMessage", "The Contributor was not found.");
response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value());
String jsonResponse = jsonObject.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
// Expected format: "word_5.mp3"
String originalFilename = multipartFile.getOriginalFilename();
logger.info("originalFilename: " + originalFilename);
AudioFormat audioFormat = CrowdsourceHelper.extractAudioFormatFromFilename(originalFilename);
logger.info("audioFormat: " + audioFormat);
Long wordIdExtractedFromFilename = CrowdsourceHelper.extractWordIdFromFilename(originalFilename);
logger.info("wordIdExtractedFromFilename: " + wordIdExtractedFromFilename);
Word word = wordDao.read(wordIdExtractedFromFilename);
logger.info("word: " + word);
if (word == null) {
jsonObject.put("result", "error");
jsonObject.put("errorMessage", "A Word with ID " + wordIdExtractedFromFilename + " was not found.");
response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value());
String jsonResponse = jsonObject.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
String contentType = multipartFile.getContentType();
logger.info("contentType: " + contentType);
try {
byte[] bytes = multipartFile.getBytes();
logger.info("bytes.length: " + bytes.length);
// Store a backup of the original CSV file on the filesystem (in case it will be needed for debugging)
// TODO
// Convert from MultipartFile to File, and extract audio duration
String tmpDir = System.getProperty("java.io.tmpdir");
File tmpDirElimuAi = new File(tmpDir, "elimu-ai");
tmpDirElimuAi.mkdir();
File file = new File(tmpDirElimuAi, multipartFile.getOriginalFilename());
logger.info("file: " + file);
multipartFile.transferTo(file);
Long durationMs = AudioMetadataExtractionHelper.getDurationInMilliseconds(file);
logger.info("durationMs: " + durationMs);
// Store the audio recording in the database
Audio audio = new Audio();
audio.setTimeLastUpdate(Calendar.getInstance());
audio.setContentType(contentType);
audio.setWord(word);
audio.setTitle(word.getText().toLowerCase());
audio.setTranscription(word.getText().toLowerCase());
audio.setBytes(bytes);
audio.setDurationMs(durationMs);
audio.setAudioFormat(audioFormat);
audioDao.create(audio);
AudioContributionEvent audioContributionEvent = new AudioContributionEvent();
audioContributionEvent.setContributor(contributor);
audioContributionEvent.setTime(Calendar.getInstance());
audioContributionEvent.setTimeSpentMs(timeSpentMs);
audioContributionEvent.setPlatform(Platform.CROWDSOURCE_APP);
audioContributionEvent.setAudio(audio);
audioContributionEvent.setRevisionNumber(audio.getRevisionNumber());
audioContributionEventDao.create(audioContributionEvent);
String contentUrl = "http://" + EnvironmentContextLoaderListener.PROPERTIES.getProperty("content.language").toLowerCase() + ".elimu.ai/content/multimedia/audio/edit/" + audio.getId();
DiscordHelper.sendChannelMessage("Audio created: " + contentUrl, "\"" + audio.getTranscription() + "\"", "Comment: \"" + audioContributionEvent.getComment() + "\"", null, null);
} catch (Exception ex) {
logger.error(ex);
jsonObject.put("result", "error");
jsonObject.put("errorMessage", ex.getMessage());
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
String jsonResponse = jsonObject.toString();
logger.info("jsonResponse: " + jsonResponse);
return jsonResponse;
}
use of ai.elimu.model.contributor.AudioContributionEvent in project webapp by elimu-ai.
the class AudioCreateController method handleSubmit.
@RequestMapping(method = RequestMethod.POST)
public String handleSubmit(HttpServletRequest request, HttpSession session, /*@Valid*/
Audio audio, @RequestParam("bytes") MultipartFile multipartFile, BindingResult result, Model model) {
logger.info("handleSubmit");
try {
byte[] bytes = multipartFile.getBytes();
if (multipartFile.isEmpty() || (bytes == null) || (bytes.length == 0)) {
result.rejectValue("bytes", "NotNull");
} else {
String originalFileName = multipartFile.getOriginalFilename();
logger.info("originalFileName: " + originalFileName);
if (originalFileName.toLowerCase().endsWith(".mp3")) {
audio.setAudioFormat(AudioFormat.MP3);
} else if (originalFileName.toLowerCase().endsWith(".ogg")) {
audio.setAudioFormat(AudioFormat.OGG);
} else if (originalFileName.toLowerCase().endsWith(".wav")) {
audio.setAudioFormat(AudioFormat.WAV);
} else {
result.rejectValue("bytes", "typeMismatch");
}
if (audio.getAudioFormat() != null) {
String contentType = multipartFile.getContentType();
logger.info("contentType: " + contentType);
audio.setContentType(contentType);
audio.setBytes(bytes);
// TODO: convert to a default audio format?
// Convert from MultipartFile to File, and extract audio duration
String tmpDir = System.getProperty("java.io.tmpdir");
File tmpDirElimuAi = new File(tmpDir, "elimu-ai");
tmpDirElimuAi.mkdir();
File file = new File(tmpDirElimuAi, multipartFile.getOriginalFilename());
logger.info("file: " + file);
multipartFile.transferTo(file);
Long durationMs = AudioMetadataExtractionHelper.getDurationInMilliseconds(file);
logger.info("durationMs: " + durationMs);
audio.setDurationMs(durationMs);
}
}
} catch (IOException e) {
logger.error(e);
}
if (result.hasErrors()) {
model.addAttribute("words", wordDao.readAllOrdered());
model.addAttribute("storyBookParagraphs", storyBookParagraphDao.readAll());
model.addAttribute("contentLicenses", ContentLicense.values());
model.addAttribute("literacySkills", LiteracySkill.values());
model.addAttribute("numeracySkills", NumeracySkill.values());
model.addAttribute("timeStart", request.getParameter("timeStart"));
model.addAttribute("emojisByWordId", getEmojisByWordId());
return "content/multimedia/audio/create";
} else {
audio.setTitle(audio.getTitle().toLowerCase());
audio.setTimeLastUpdate(Calendar.getInstance());
audioDao.create(audio);
AudioContributionEvent audioContributionEvent = new AudioContributionEvent();
audioContributionEvent.setContributor((Contributor) session.getAttribute("contributor"));
audioContributionEvent.setTime(Calendar.getInstance());
audioContributionEvent.setAudio(audio);
audioContributionEvent.setRevisionNumber(audio.getRevisionNumber());
audioContributionEvent.setComment(StringUtils.abbreviate(request.getParameter("contributionComment"), 1000));
audioContributionEvent.setTimeSpentMs(System.currentTimeMillis() - Long.valueOf(request.getParameter("timeStart")));
audioContributionEvent.setPlatform(Platform.WEBAPP);
audioContributionEventDao.create(audioContributionEvent);
String contentUrl = "http://" + EnvironmentContextLoaderListener.PROPERTIES.getProperty("content.language").toLowerCase() + ".elimu.ai/content/multimedia/audio/edit/" + audio.getId();
DiscordHelper.sendChannelMessage("Audio created: " + contentUrl, "\"" + audio.getTranscription() + "\"", "Comment: \"" + audioContributionEvent.getComment() + "\"", null, null);
return "redirect:/content/multimedia/audio/list#" + audio.getId();
}
}
use of ai.elimu.model.contributor.AudioContributionEvent in project webapp by elimu-ai.
the class AudioEditController method handleSubmit.
@RequestMapping(value = "/{id}", method = RequestMethod.POST)
public String handleSubmit(HttpServletRequest request, HttpSession session, Audio audio, @RequestParam("bytes") MultipartFile multipartFile, BindingResult result, Model model) {
logger.info("handleSubmit");
try {
byte[] bytes = multipartFile.getBytes();
if (multipartFile.isEmpty() || (bytes == null) || (bytes.length == 0)) {
result.rejectValue("bytes", "NotNull");
} else {
String originalFileName = multipartFile.getOriginalFilename();
logger.info("originalFileName: " + originalFileName);
if (originalFileName.toLowerCase().endsWith(".mp3")) {
audio.setAudioFormat(AudioFormat.MP3);
} else if (originalFileName.toLowerCase().endsWith(".ogg")) {
audio.setAudioFormat(AudioFormat.OGG);
} else if (originalFileName.toLowerCase().endsWith(".wav")) {
audio.setAudioFormat(AudioFormat.WAV);
} else {
result.rejectValue("bytes", "typeMismatch");
}
if (audio.getAudioFormat() != null) {
String contentType = multipartFile.getContentType();
logger.info("contentType: " + contentType);
audio.setContentType(contentType);
audio.setBytes(bytes);
// TODO: convert to a default audio format?
// Convert from MultipartFile to File, and extract audio duration
String tmpDir = System.getProperty("java.io.tmpdir");
File tmpDirElimuAi = new File(tmpDir, "elimu-ai");
tmpDirElimuAi.mkdir();
File file = new File(tmpDirElimuAi, multipartFile.getOriginalFilename());
logger.info("file: " + file);
multipartFile.transferTo(file);
Long durationMs = AudioMetadataExtractionHelper.getDurationInMilliseconds(file);
logger.info("durationMs: " + durationMs);
audio.setDurationMs(durationMs);
}
}
} catch (IOException e) {
logger.error(e);
}
if (result.hasErrors()) {
model.addAttribute("audio", audio);
model.addAttribute("words", wordDao.readAllOrdered());
model.addAttribute("storyBookParagraphs", storyBookParagraphDao.readAll());
model.addAttribute("contentLicenses", ContentLicense.values());
model.addAttribute("literacySkills", LiteracySkill.values());
model.addAttribute("numeracySkills", NumeracySkill.values());
model.addAttribute("timeStart", request.getParameter("timeStart"));
model.addAttribute("audioContributionEvents", audioContributionEventDao.readAll(audio));
model.addAttribute("audioPeerReviewEvents", audioPeerReviewEventDao.readAll(audio));
model.addAttribute("letters", letterDao.readAllOrdered());
model.addAttribute("numbers", numberDao.readAllOrdered());
model.addAttribute("words", wordDao.readAllOrdered());
model.addAttribute("emojisByWordId", getEmojisByWordId());
return "content/multimedia/audio/edit";
} else {
audio.setTitle(audio.getTitle().toLowerCase());
audio.setTimeLastUpdate(Calendar.getInstance());
audio.setRevisionNumber(audio.getRevisionNumber() + 1);
audioDao.update(audio);
AudioContributionEvent audioContributionEvent = new AudioContributionEvent();
audioContributionEvent.setContributor((Contributor) session.getAttribute("contributor"));
audioContributionEvent.setTime(Calendar.getInstance());
audioContributionEvent.setAudio(audio);
audioContributionEvent.setRevisionNumber(audio.getRevisionNumber());
audioContributionEvent.setComment(StringUtils.abbreviate(request.getParameter("contributionComment"), 1000));
audioContributionEvent.setTimeSpentMs(System.currentTimeMillis() - Long.valueOf(request.getParameter("timeStart")));
audioContributionEvent.setPlatform(Platform.WEBAPP);
audioContributionEventDao.create(audioContributionEvent);
String contentUrl = "http://" + EnvironmentContextLoaderListener.PROPERTIES.getProperty("content.language").toLowerCase() + ".elimu.ai/content/multimedia/audio/edit/" + audio.getId();
DiscordHelper.sendChannelMessage("Audio edited: " + contentUrl, "\"" + audio.getTranscription() + "\"", "Comment: \"" + audioContributionEvent.getComment() + "\"", null, null);
return "redirect:/content/multimedia/audio/list#" + audio.getId();
}
}
use of ai.elimu.model.contributor.AudioContributionEvent in project webapp by elimu-ai.
the class AudioPeerReviewEventCreateController method handleSubmit.
/**
* Note: The logic in this method is similar to the one used at {@link AudioPeerReviewsRestController#uploadAudioPeerReview}
*/
@RequestMapping(method = RequestMethod.POST)
public String handleSubmit(@RequestParam Long audioContributionEventId, @RequestParam Boolean approved, @RequestParam(required = false) String comment, HttpSession session) {
logger.info("handleSubmit");
Contributor contributor = (Contributor) session.getAttribute("contributor");
logger.info("audioContributionEventId: " + audioContributionEventId);
AudioContributionEvent audioContributionEvent = audioContributionEventDao.read(audioContributionEventId);
logger.info("audioContributionEvent: " + audioContributionEvent);
// Store the peer review event
AudioPeerReviewEvent audioPeerReviewEvent = new AudioPeerReviewEvent();
audioPeerReviewEvent.setContributor(contributor);
audioPeerReviewEvent.setAudioContributionEvent(audioContributionEvent);
audioPeerReviewEvent.setApproved(approved);
audioPeerReviewEvent.setComment(StringUtils.abbreviate(comment, 1000));
audioPeerReviewEvent.setTime(Calendar.getInstance());
audioPeerReviewEvent.setPlatform(Platform.WEBAPP);
audioPeerReviewEventDao.create(audioPeerReviewEvent);
String contentUrl = "http://" + EnvironmentContextLoaderListener.PROPERTIES.getProperty("content.language").toLowerCase() + ".elimu.ai/content/multimedia/audio/edit/" + audioContributionEvent.getAudio().getId();
DiscordHelper.sendChannelMessage("Audio peer-reviewed: " + contentUrl, "\"" + audioContributionEvent.getAudio().getTitle() + "\"", "Comment: \"" + audioPeerReviewEvent.getComment() + "\"", audioPeerReviewEvent.isApproved(), null);
// Update the audio's peer review status
int approvedCount = 0;
int notApprovedCount = 0;
for (AudioPeerReviewEvent peerReviewEvent : audioPeerReviewEventDao.readAll(audioContributionEvent)) {
if (peerReviewEvent.isApproved()) {
approvedCount++;
} else {
notApprovedCount++;
}
}
logger.info("approvedCount: " + approvedCount);
logger.info("notApprovedCount: " + notApprovedCount);
Audio audio = audioContributionEvent.getAudio();
if (approvedCount >= notApprovedCount) {
audio.setPeerReviewStatus(PeerReviewStatus.APPROVED);
} else {
audio.setPeerReviewStatus(PeerReviewStatus.NOT_APPROVED);
}
audioDao.update(audio);
return "redirect:/content/multimedia/audio/edit/" + audioContributionEvent.getAudio().getId() + "#contribution-events";
}
Aggregations