Skip to content

Commit

Permalink
feat: #86 Upload LetterLearningEvents
Browse files Browse the repository at this point in the history
- Skip upload if not `TEST`/`PROD`
  • Loading branch information
nya-elimu committed Nov 18, 2020
1 parent 037477d commit 628c0cb
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package ai.elimu.analytics.dao;

import android.database.Cursor;

import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;

import java.util.List;

import ai.elimu.analytics.entity.LetterLearningEvent;

Expand All @@ -10,4 +15,10 @@ public interface LetterLearningEventDao {

@Insert
void insert(LetterLearningEvent letterLearningEvent);

@Query("SELECT * FROM LetterLearningEvent ORDER BY time DESC")
List<LetterLearningEvent> loadAllOrderedByTimeDesc();

@Query("SELECT * FROM LetterLearningEvent ORDER BY time")
Cursor loadAllOrderedByTime();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ai.elimu.analytics.rest;

import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;

public interface LetterLearningEventService {

@Multipart
@POST("analytics/letter-learning-events/csv")
Call<ResponseBody> uploadCsvFile(@Part MultipartBody.Part part);
}
111 changes: 88 additions & 23 deletions app/src/main/java/ai/elimu/analytics/task/ExportEventsToCsvWorker.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
import java.text.SimpleDateFormat;
import java.util.List;

import ai.elimu.analytics.dao.LetterLearningEventDao;
import ai.elimu.analytics.dao.StoryBookLearningEventDao;
import ai.elimu.analytics.dao.WordLearningEventDao;
import ai.elimu.analytics.db.RoomDb;
import ai.elimu.analytics.entity.LetterLearningEvent;
import ai.elimu.analytics.entity.StoryBookLearningEvent;
import ai.elimu.analytics.entity.WordLearningEvent;

Expand All @@ -33,29 +35,31 @@ public ExportEventsToCsvWorker(@NonNull Context context, @NonNull WorkerParamete
@Override
public Result doWork() {
Log.i(getClass().getName(), "doWork");
exportStoryBookLearningEventsToCsv();

exportLetterLearningEventsToCsv();
exportWordLearningEventsToCsv();
exportStoryBookLearningEventsToCsv();

return Result.success();
}
private void exportStoryBookLearningEventsToCsv() {
Log.i(getClass().getName(), "exportStoryBookLearningEventsToCsv");
// Extract StoryBookLearningEvents from the database that have not yet been exported to CSV.

private void exportLetterLearningEventsToCsv() {
Log.i(getClass().getName(), "exportLetterLearningEventsToCsv");

// Extract LetterLearningEvents from the database that have not yet been exported to CSV.
RoomDb roomDb = RoomDb.getDatabase(getApplicationContext());
StoryBookLearningEventDao storyBookLearningEventDao = roomDb.storyBookLearningEventDao();
List<StoryBookLearningEvent> storyBookLearningEvents = storyBookLearningEventDao.loadAll();
Log.i(getClass().getName(), "storyBookLearningEvents.size(): " + storyBookLearningEvents.size());
LetterLearningEventDao letterLearningEventDao = roomDb.letterLearningEventDao();
List<LetterLearningEvent> letterLearningEvents = letterLearningEventDao.loadAllOrderedByTimeDesc();
Log.i(getClass().getName(), "letterLearningEvents.size(): " + letterLearningEvents.size());

CSVFormat csvFormat = CSVFormat.DEFAULT
.withHeader(
"id",
"time",
"android_id",
"package_name",
"storybook_id",
"letter_id",
"letter_text",
"learning_event_type"
);
StringWriter stringWriter = new StringWriter();
Expand All @@ -64,35 +68,36 @@ private void exportStoryBookLearningEventsToCsv() {

// Generate one CSV file per day of events
String dateOfPreviousEvent = null;
for (StoryBookLearningEvent storyBookLearningEvent : storyBookLearningEvents) {
// Export event to CSV file. Example format: "files/storybook-learning-events/7161a85a0e4751cd_storybook-learning-events_2020-03-21.csv"
for (LetterLearningEvent letterLearningEvent : letterLearningEvents) {
// Export event to CSV file. Example format: "files/letter-learning-events/7161a85a0e4751cd_letter-learning-events_2020-03-21.csv"
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(storyBookLearningEvent.getTime().getTime());
String date = simpleDateFormat.format(letterLearningEvent.getTime().getTime());
if (!date.equals(dateOfPreviousEvent)) {
// Reset file content
stringWriter = new StringWriter();
csvPrinter = new CSVPrinter(stringWriter, csvFormat);
}
dateOfPreviousEvent = date;
String csvFilename = storyBookLearningEvent.getAndroidId() + "_storybook-learning-events_" + date + ".csv";
String csvFilename = letterLearningEvent.getAndroidId() + "_letter-learning-events_" + date + ".csv";
Log.i(getClass().getName(), "csvFilename: " + csvFilename);

csvPrinter.printRecord(
storyBookLearningEvent.getId(),
storyBookLearningEvent.getTime().getTimeInMillis(),
storyBookLearningEvent.getAndroidId(),
storyBookLearningEvent.getPackageName(),
storyBookLearningEvent.getStoryBookId(),
storyBookLearningEvent.getLearningEventType()
letterLearningEvent.getId(),
letterLearningEvent.getTime().getTimeInMillis(),
letterLearningEvent.getAndroidId(),
letterLearningEvent.getPackageName(),
letterLearningEvent.getLetterId(),
letterLearningEvent.getLetterText(),
letterLearningEvent.getLearningEventType()
);
csvPrinter.flush();

String csvFileContent = stringWriter.toString();

// Write the content to the CSV file
File filesDir = getApplicationContext().getFilesDir();
File storyBookLearningEventsDir = new File(filesDir, "storybook-learning-events");
File csvFile = new File(storyBookLearningEventsDir, csvFilename);
File letterLearningEventsDir = new File(filesDir, "letter-learning-events");
File csvFile = new File(letterLearningEventsDir, csvFilename);
FileUtils.writeStringToFile(csvFile, csvFileContent, "UTF-8");
}
} catch (IOException e) {
Expand Down Expand Up @@ -161,4 +166,64 @@ private void exportWordLearningEventsToCsv() {
Log.e(getClass().getName(), null, e);
}
}

private void exportStoryBookLearningEventsToCsv() {
Log.i(getClass().getName(), "exportStoryBookLearningEventsToCsv");

// Extract StoryBookLearningEvents from the database that have not yet been exported to CSV.
RoomDb roomDb = RoomDb.getDatabase(getApplicationContext());
StoryBookLearningEventDao storyBookLearningEventDao = roomDb.storyBookLearningEventDao();
List<StoryBookLearningEvent> storyBookLearningEvents = storyBookLearningEventDao.loadAll();
Log.i(getClass().getName(), "storyBookLearningEvents.size(): " + storyBookLearningEvents.size());

CSVFormat csvFormat = CSVFormat.DEFAULT
.withHeader(
"id",
"time",
"android_id",
"package_name",
"storybook_id",
"learning_event_type"
);
StringWriter stringWriter = new StringWriter();
try {
CSVPrinter csvPrinter = new CSVPrinter(stringWriter, csvFormat);

// Generate one CSV file per day of events
String dateOfPreviousEvent = null;
for (StoryBookLearningEvent storyBookLearningEvent : storyBookLearningEvents) {
// Export event to CSV file. Example format: "files/storybook-learning-events/7161a85a0e4751cd_storybook-learning-events_2020-03-21.csv"
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = simpleDateFormat.format(storyBookLearningEvent.getTime().getTime());
if (!date.equals(dateOfPreviousEvent)) {
// Reset file content
stringWriter = new StringWriter();
csvPrinter = new CSVPrinter(stringWriter, csvFormat);
}
dateOfPreviousEvent = date;
String csvFilename = storyBookLearningEvent.getAndroidId() + "_storybook-learning-events_" + date + ".csv";
Log.i(getClass().getName(), "csvFilename: " + csvFilename);

csvPrinter.printRecord(
storyBookLearningEvent.getId(),
storyBookLearningEvent.getTime().getTimeInMillis(),
storyBookLearningEvent.getAndroidId(),
storyBookLearningEvent.getPackageName(),
storyBookLearningEvent.getStoryBookId(),
storyBookLearningEvent.getLearningEventType()
);
csvPrinter.flush();

String csvFileContent = stringWriter.toString();

// Write the content to the CSV file
File filesDir = getApplicationContext().getFilesDir();
File storyBookLearningEventsDir = new File(filesDir, "storybook-learning-events");
File csvFile = new File(storyBookLearningEventsDir, csvFilename);
FileUtils.writeStringToFile(csvFile, csvFileContent, "UTF-8");
}
} catch (IOException e) {
Log.e(getClass().getName(), null, e);
}
}
}
66 changes: 56 additions & 10 deletions app/src/main/java/ai/elimu/analytics/task/UploadEventsWorker.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.Arrays;

import ai.elimu.analytics.BaseApplication;
import ai.elimu.analytics.BuildConfig;
import ai.elimu.analytics.rest.LetterLearningEventService;
import ai.elimu.analytics.rest.StoryBookLearningEventService;
import ai.elimu.analytics.rest.WordLearningEventService;
import okhttp3.MediaType;
Expand All @@ -33,20 +35,23 @@ public UploadEventsWorker(@NonNull Context context, @NonNull WorkerParameters wo
public Result doWork() {
Log.i(getClass().getName(), "doWork");

uploadStoryBookLearningEvents();
uploadWordLearningEvents();
if (!"debug".equals(BuildConfig.BUILD_TYPE)) {
uploadLetterLearningEvents();
uploadWordLearningEvents();
uploadStoryBookLearningEvents();
}

return Result.success();
}
private void uploadStoryBookLearningEvents() {
Log.i(getClass().getName(), "uploadStoryBookLearningEvents");

private void uploadLetterLearningEvents() {
Log.i(getClass().getName(), "uploadLetterLearningEvents");

// Upload CSV files to the server
File filesDir = getApplicationContext().getFilesDir();
File storyBookLearningEventsDir = new File(filesDir, "storybook-learning-events");
Log.i(getClass().getName(), "Uploading CSV files from " + storyBookLearningEventsDir);
File[] files = storyBookLearningEventsDir.listFiles();
File letterLearningEventsDir = new File(filesDir, "letter-learning-events");
Log.i(getClass().getName(), "Uploading CSV files from " + letterLearningEventsDir);
File[] files = letterLearningEventsDir.listFiles();
if (files != null) {
Log.i(getClass().getName(), "files.length: " + files.length);
Arrays.sort(files);
Expand All @@ -56,10 +61,10 @@ private void uploadStoryBookLearningEvents() {

BaseApplication baseApplication = (BaseApplication) getApplicationContext();
Retrofit retrofit = baseApplication.getRetrofit();
StoryBookLearningEventService storyBookLearningEventService = retrofit.create(StoryBookLearningEventService.class);
LetterLearningEventService letterLearningEventService = retrofit.create(LetterLearningEventService.class);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
Call<ResponseBody> call = storyBookLearningEventService.uploadCsvFile(part);
Call<ResponseBody> call = letterLearningEventService.uploadCsvFile(part);
Log.i(getClass().getName(), "call.request(): " + call.request());
try {
Response<ResponseBody> response = call.execute();
Expand Down Expand Up @@ -120,4 +125,45 @@ private void uploadWordLearningEvents() {
}
}
}

private void uploadStoryBookLearningEvents() {
Log.i(getClass().getName(), "uploadStoryBookLearningEvents");

// Upload CSV files to the server
File filesDir = getApplicationContext().getFilesDir();
File storyBookLearningEventsDir = new File(filesDir, "storybook-learning-events");
Log.i(getClass().getName(), "Uploading CSV files from " + storyBookLearningEventsDir);
File[] files = storyBookLearningEventsDir.listFiles();
if (files != null) {
Log.i(getClass().getName(), "files.length: " + files.length);
Arrays.sort(files);
for (int i = 0; i < files.length; i++) {
File file = files[i];
Log.i(getClass().getName(), "file.getName(): " + file.getName());

BaseApplication baseApplication = (BaseApplication) getApplicationContext();
Retrofit retrofit = baseApplication.getRetrofit();
StoryBookLearningEventService storyBookLearningEventService = retrofit.create(StoryBookLearningEventService.class);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
Call<ResponseBody> call = storyBookLearningEventService.uploadCsvFile(part);
Log.i(getClass().getName(), "call.request(): " + call.request());
try {
Response<ResponseBody> response = call.execute();
Log.i(getClass().getName(), "response: " + response);
Log.i(getClass().getName(), "response.isSuccessful(): " + response.isSuccessful());
if (response.isSuccessful()) {
String bodyString = response.body().string();
Log.i(getClass().getName(), "bodyString: " + bodyString);
} else {
String errorBodyString = response.errorBody().string();
Log.e(getClass().getName(), "errorBodyString: " + errorBodyString);
// TODO: Handle error
}
} catch (IOException e) {
Log.e(getClass().getName(), null, e);
}
}
}
}
}

0 comments on commit 628c0cb

Please sign in to comment.