app/src/main/java/com/davidmiguel/gobees/data/source/local/DataGenerator.java
/*
* GoBees
* Copyright (c) 2016 - 2017 David Miguel Lozano
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
*/
package com.davidmiguel.gobees.data.source.local;
import android.content.Context;
import android.location.Location;
import com.davidmiguel.gobees.R;
import com.davidmiguel.gobees.data.model.Apiary;
import com.davidmiguel.gobees.data.model.Hive;
import com.davidmiguel.gobees.data.model.MeteoRecord;
import com.davidmiguel.gobees.data.model.Record;
import com.davidmiguel.gobees.data.model.Recording;
import com.davidmiguel.gobees.data.source.GoBeesDataSource;
import com.davidmiguel.gobees.utils.DateTimeUtils;
import com.google.common.collect.Lists;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* Generate sample data: 1 apiary with 3 hives. Each hive with 3 recordings:
* - normal activity - good weather.
* - very low activity - bad weather.
* - swarming activity - good weather.
*/
public class DataGenerator implements GoBeesDataSource.SaveRecordingCallback {
private static final double LAT = 42.352083;
private static final double LON = -3.697586;
// SAMPLE 1: normal activity - good weather
private static final int[] GOOD_NUM_BEES = {
0, 0, 0, 0, 0, 0, 1, 0, 1, 2, 0, 1, 0, // 7h
1, 1, 2, 1, 2, 2, 2, 3, 3, 4, 2, 4, // 8h
4, 5, 7, 6, 6, 7, 5, 4, 6, 5, 4, 7, // 9h
10, 9, 11, 12, 11, 11, 10, 12, 11, 10, 11, 11, // 10h
12, 13, 13, 13, 12, 13, 13, 12, 12, 11, 15, 14, // 11h
14, 15, 15, 14, 15, 16, 15, 15, 17, 21, 19, 25, // 12h
26, 25, 28, 32, 30, 26, 22, 17, 16, 17, 15, 14, // 13h
14, 10, 15, 14, 14, 11, 13, 12, 10, 9, 7, 8, // 14h
8, 7, 8, 8, 8, 9, 9, 8, 8, 9, 8, 7, // 15h
6, 5, 7, 5, 5, 5, 6, 5, 5, 7, 6, 5, // 16h
5, 4, 4, 4, 6, 4, 5, 4, 4, 4, 5, 4, // 17h
3, 3, 4, 2, 2, 4, 4, 3, 2, 2, 2, 2, // 18h
1, 2, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, //19h
0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 // 20h
};
private static final double[] GOOD_WEATHER_TEMP = {
7.0, 10.0, 11.0, 15.0, 18.0, 21.0, 25.0, 26.0, 26.0, 26.0, 22.0, 20.0, 15.0, 14.0
};
private static final double[] GOOD_WEATHER_RAIN = {
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.5
};
private static final double[] GOOD_WEATHER_WIND = {
3.0, 2.0, 2.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 3.0, 4.0, 4.0
};
// SAMPLE 2: very low activity - bad weather
private static final int[] VERY_LOW_NUM_BEES = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, // 7h
0, 0, 1, 1, 0, 0, 1, 1, 2, 1, 0, 0, // 8h
0, 1, 1, 1, 1, 2, 2, 1, 0, 0, 0, 0, // 9h
1, 1, 1, 2, 2, 1, 3, 1, 1, 0, 1, 1, // 10h
2, 3, 3, 3, 2, 3, 3, 2, 2, 1, 0, 0, // 11h
0, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, // 12h
1, 1, 0, 2, 2, 2, 2, 3, 3, 3, 4, 3, // 13h
4, 3, 5, 4, 4, 3, 3, 2, 1, 3, 2, 2, // 14h
2, 1, 2, 3, 3, 2, 1, 2, 2, 2, 0, 0, // 15h
1, 1, 1, 2, 2, 1, 3, 1, 1, 1, 0, 1, // 16h
0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, // 17h
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, // 18h
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //19h
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 20h
};
private static final double[] BAD_WEATHER_TEMP = {
1.0, 1.0, 2.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3.0, 2.0, 1.0, 0.0, 0.0
};
private static final double[] BAD_WEATHER_RAIN = {
1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 5.0, 2.0, 1.0
};
private static final double[] BAD_WEATHER_WIND = {
10.0, 8.0, 8.0, 5.0, 4.0, 4.0, 4.0, 5.0, 5.0, 10.0, 6.0, 1.0, 4.0, 4.0
};
// SAMPLE 3: swarming activity - good weather
private static final int[] SWARMING_NUM_BEES = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7h
1, 2, 1, 1, 1, 2, 2, 3, 1, 1, 2, 1, // 8h
2, 3, 2, 4, 6, 7, 5, 4, 6, 5, 4, 7, // 9h
10, 9, 11, 12, 30, 38, 39, 39, 10, 9, 11, 10, // 10h
10, 9, 8, 10, 12, 13, 13, 12, 12, 11, 10, 10, // 11h
8, 7, 9, 9, 12, 13, 12, 12, 10, 11, 10, 9, // 12h
9, 8, 8, 7, 8, 6, 8, 8, 9, 10, 11, 12, // 13h
11, 12, 13, 14, 13, 12, 13, 12, 10, 9, 7, 6, // 14h
6, 7, 8, 7, 8, 9, 7, 8, 7, 9, 7, 7, // 15h
5, 5, 6, 4, 5, 5, 4, 5, 5, 7, 4, 5, // 16h
3, 4, 5, 4, 6, 3, 5, 4, 3, 4, 3, 4, // 17h
3, 1, 2, 2, 2, 3, 2, 3, 2, 2, 1, 2, // 18h
2, 1, 2, 0, 2, 1, 0, 2, 0, 1, 0, 1, //19h
1, 0, 2, 1, 1, 0, 1, 1, 2, 1, 0, 0 // 20h
};
private static final double[] SWARMING_WEATHER_TEMP = {
17.0, 18.0, 20.0, 22.0, 25.0, 28.0, 30.0, 33.0, 30.0, 28.0, 25.0, 25.0, 20.0, 20.0
};
private static final double[] SWARMING_WEATHER_RAIN = {
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
};
private static final double[] SWARMING_WEATHER_WIND = {
1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 2.0
};
private Context context;
private GoBeesDataSource goBeesDataSource;
public DataGenerator(Context context, GoBeesDataSource goBeesDataSource) {
this.context = context;
this.goBeesDataSource = goBeesDataSource;
}
public void generateData() {
// Generate apiary
Apiary apiary = generateApiary();
// Generate hives
List<Hive> hives = Lists.newArrayList(
generateHive(apiary, 1),
generateHive(apiary, 2),
generateHive(apiary, 3)
);
// Generate recordings
Date date;
// SAMPLE 1: normal activity - good weather
date = new Date(1474347600000L); // 20/09/16 7:00
for (Hive hive : hives) {
generateRecording(hive, date, GOOD_NUM_BEES);
}
generateWeatherData(apiary, date, GOOD_WEATHER_TEMP, GOOD_WEATHER_RAIN, GOOD_WEATHER_WIND);
// SAMPLE 2: very low activity - bad weather
date = new Date(1483596000000L); // 05/01/17 7:00
for (Hive hive : hives) {
generateRecording(hive, date, VERY_LOW_NUM_BEES);
}
generateWeatherData(apiary, date, BAD_WEATHER_TEMP, BAD_WEATHER_RAIN, BAD_WEATHER_WIND);
// SAMPLE 3: swarming activity - good weather
date = new Date(1474779600000L); // 25/09/16 7:00
for (Hive hive : hives) {
generateRecording(hive, date, SWARMING_NUM_BEES);
}
generateWeatherData(apiary, date, SWARMING_WEATHER_TEMP,
SWARMING_WEATHER_RAIN, SWARMING_WEATHER_WIND);
}
/**
* Generate a new apiary.
*
* @return new apiary.
*/
private Apiary generateApiary() {
Apiary apiary = new Apiary();
// Set id
final long[] id = new long[1];
goBeesDataSource.getNextApiaryId(new GoBeesDataSource.GetNextApiaryIdCallback() {
@Override
public void onNextApiaryIdLoaded(long apiaryId) {
id[0] = apiaryId;
}
});
apiary.setId(id[0]);
// Set name
apiary.setName(context.getString(R.string.sample_apiary_name));
// Set random location
Location location = getRandomNearLocation(LAT, LON);
apiary.setLocationLat(location.getLatitude());
apiary.setLocationLong(location.getLongitude());
// Set notes
apiary.setNotes(context.getString(R.string.sample_apiary_notes));
// Save apiary
goBeesDataSource.saveApiary(apiary, this);
goBeesDataSource.refreshApiaries();
return apiary;
}
/**
* Generate a new hive.
*
* @param apiary apiary which it belongs.
* @param number number to generate name.
* @return new hive.
*/
private Hive generateHive(Apiary apiary, int number) {
Hive hive = new Hive();
// Set id
final long[] id = new long[1];
goBeesDataSource.getNextHiveId(new GoBeesDataSource.GetNextHiveIdCallback() {
@Override
public void onNextHiveIdLoaded(long hiveId) {
id[0] = hiveId;
}
});
hive.setId(id[0]);
// Set name
hive.setName(String.format(context.getString(R.string.sample_hive_name), number));
// Set notes
hive.setNotes(context.getString(R.string.sample_hive_notes));
// Set last revision
hive.setLastRevision(new Date());
// Save hive
goBeesDataSource.saveHive(apiary.getId(), hive, this);
return hive;
}
private Recording generateRecording(Hive hive, Date date, int[] numBees) {
Date hour = new Date(date.getTime());
List<Record> records = new ArrayList<>(numBees.length);
// Generate records
for (int numBee : numBees) {
records.add(new Record(hour, numBee));
hour = DateTimeUtils.sumTimeToDate(hour, 0, 5, 0);
}
// Save recording
goBeesDataSource.saveRecords(hive.getId(), records, this);
return new Recording(date, records);
}
private void generateWeatherData(Apiary apiary, Date date,
double[] temp, double[] rain, double[] wind) {
Date hour = new Date(date.getTime());
// Generate meteo record
List<MeteoRecord> meteoRecords = new ArrayList<>(temp.length);
for (int i = 0; i < temp.length; i++) {
meteoRecords.add(new MeteoRecord(hour, "", -1, "", temp[i], -1, -1, -1, -1,
wind[i], -1, -1, rain[i], -1));
hour = DateTimeUtils.sumTimeToDate(hour, 1, 0, 0);
}
// Save meteo records
goBeesDataSource.saveMeteoRecords(apiary.getId(), meteoRecords);
}
/**
* Generate random location.
*
* @param latitude center latitude.
* @param longitude center longitude.
* @return random location.
*/
private Location getRandomNearLocation(double latitude, double longitude) {
Random random = new Random();
double lat = BigDecimal.valueOf(latitude + random.nextInt(100) / 100d)
.setScale(7, RoundingMode.HALF_UP).doubleValue();
double lon = BigDecimal.valueOf(longitude + random.nextInt(100) / 100d)
.setScale(7, RoundingMode.HALF_UP).doubleValue();
Location location = new Location("");
location.setLatitude(lat);
location.setLongitude(lon);
return location;
}
@Override
public void onSuccess() {
// Nothing to do
}
@Override
public void onFailure() {
// Nothing to do
}
@Override
public void onRecordingTooShort() {
// Nothing to do
}
}