use of com.cpjd.roblu.models.RCheckout in project Roblu by wdavies973.
the class TeamTabAdapter method createMatch.
/**
* Creates a new match with the specified parameter,
* this method is used by the manual match creator, however,
* most users will likely just use TBA.com importing.
* @param name the name of the match
* @param isRed true if this team is on the red alliance
* @return the position of the sorted, created match
*/
public int createMatch(String name, boolean isRed) {
RTab tab = new RTab(TeamViewer.team.getNumber(), name, Utils.duplicateRMetricArray(form.getMatch()), isRed, false, 0);
int position = TeamViewer.team.addTab(tab);
TeamViewer.team.setLastEdit(System.currentTimeMillis());
new IO(context).saveTeam(event.getID(), TeamViewer.team);
// If these event is cloud synced, a new checkout needs to be packaged
if (event.isCloudEnabled()) {
RTeam newTeam = new RTeam(TeamViewer.team.getName(), TeamViewer.team.getNumber(), TeamViewer.team.getID());
newTeam.addTab(tab);
RCheckout checkout = new RCheckout(newTeam);
/*
* It would require a lot more code to check all devices and be sure that a new ID is
* valid, so generate a random one. The chances of an error occurring are so low, this is acceptable (somewhat :\)
*/
checkout.setID(new Random().nextInt(Integer.MAX_VALUE - 50_000) + 20_000);
checkout.setStatus(HandoffStatus.AVAILABLE);
new IO(context).savePendingCheckout(checkout);
}
Bundle bundle = new Bundle();
bundle.putSerializable("event", event);
bundle.putSerializable("form", form);
bundle.putBoolean("readOnly", false);
bundle.putInt("position", position);
Match match = new Match();
match.setArguments(bundle);
notifyDataSetChanged();
return position + 1;
}
use of com.cpjd.roblu.models.RCheckout in project Roblu by wdavies973.
the class EventDepacker method run.
@Override
public void run() {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);
Log.d("RBS", "Executing EventDepacker task...");
ObjectMapper mapper = new ObjectMapper().configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
RSettings settings = io.loadSettings();
RSyncSettings cloudSettings = io.loadCloudSettings();
cloudSettings.setTeamSyncID(0);
cloudSettings.getCheckoutSyncIDs().clear();
cloudSettings.setPurgeRequested(false);
io.saveCloudSettings(cloudSettings);
Request r = new Request(settings.getServerIP());
CloudTeamRequest ctr = new CloudTeamRequest(r, settings.getCode());
if (teamNumber != -1) {
ctr.setCode("");
ctr.setTeamNumber(teamNumber);
}
CloudCheckoutRequest ccr = new CloudCheckoutRequest(r, settings.getCode());
if (teamNumber != -1) {
ccr.setTeamCode("");
ccr.setTeamNumber(teamNumber);
}
if (teamNumber == -1 && (settings.getCode() == null || settings.getCode().equals(""))) {
if (listener != null)
listener.errorOccurred("No team code found in settings. Unable to import event.");
return;
}
// Ping
if (!r.ping()) {
if (listener != null)
listener.errorOccurred("It appears as though the server is offline. Try again later.");
return;
}
if (!ctr.isActive()) {
if (listener != null)
listener.errorOccurred("No event found on Roblu Cloud.");
return;
}
/*
* Download everything
*
*/
CloudTeam team = ctr.getTeam(-1);
REvent event;
try {
// Create a new event
event = new REvent(io.getNewEventID(), team.getActiveEventName());
event.setKey(team.getTbaKey());
// should be -1 if cloud is not enabled
event.setReadOnlyTeamNumber(teamNumber);
event.setID(io.getNewEventID());
event.setCloudEnabled(true);
io.saveEvent(event);
settings.setTeamNumber((int) team.getNumber());
settings.setRui(mapper.readValue(team.getUi(), RUI.class));
io.saveSettings(settings);
RForm form = mapper.readValue(team.getForm(), RForm.class);
io.saveForm(event.getID(), form);
} catch (Exception e) {
Log.d("RBS", "Failed to download event");
listener.errorOccurred("Failed to import Roblu Cloud event.");
return;
}
/*
* Un-package checkouts into a teams array
*/
ArrayList<RCheckout> checkouts = new ArrayList<>();
try {
CloudCheckout[] pulledCheckouts = ccr.pullCheckouts(null, true);
for (CloudCheckout s : pulledCheckouts) checkouts.add(mapper.readValue(s.getContent(), RCheckout.class));
} catch (IOException e) {
Log.d("RBS", "Failed to de-package checkouts.");
listener.errorOccurred("Failed to import Roblu Cloud event.");
return;
}
/*
* Start sorting the checkouts into teams
*/
ArrayList<RTeam> teams = new ArrayList<>();
for (RCheckout checkout : checkouts) {
// First, check if the team has already been created
boolean found = false;
for (RTeam t : teams) {
if (t.getID() == checkout.getTeam().getID()) {
// Add the checkout information to the team
t.getTabs().addAll(checkout.getTeam().getTabs());
found = true;
break;
}
t.setLastEdit(checkout.getTime());
}
// If not found, create a new team
if (!found) {
RTeam newTeam = new RTeam(checkout.getTeam().getName(), checkout.getTeam().getNumber(), checkout.getTeam().getID());
newTeam.setTabs(new ArrayList<RTab>());
newTeam.getTabs().addAll(checkout.getTeam().getTabs());
teams.add(newTeam);
}
}
Log.d("RBS", "Created " + teams.size() + " teams");
/*
* Unpack images
*/
for (RCheckout checkout : checkouts) {
for (RTab tab : checkout.getTeam().getTabs()) {
for (RMetric metric : tab.getMetrics()) {
if (metric instanceof RGallery) {
for (int i = 0; ((RGallery) metric).getImages() != null && i < ((RGallery) metric).getImages().size(); i++) {
int picID = io.savePicture(event.getID(), ((RGallery) metric).getImages().get(i));
if (picID != -1) {
((RGallery) metric).setPictureIDs(new ArrayList<Integer>());
((RGallery) metric).getPictureIDs().add(picID);
}
}
if (((RGallery) metric).getImages() != null)
((RGallery) metric).getImages().clear();
}
}
}
}
/*
* Save teams
* -Teams don't need to be verified since the form has also been pulled from the server
*/
for (RTeam t : teams) {
Collections.sort(t.getTabs());
io.saveTeam(event.getID(), t);
}
// Remove all the other synced events
REvent[] events = io.loadEvents();
for (int i = 0; events != null && i < events.length; i++) {
events[i].setCloudEnabled(events[i].getID() == event.getID());
io.saveEvent(events[i]);
}
/*
* Add default sync ids
*/
for (RCheckout checkout : checkouts) {
cloudSettings.getCheckoutSyncIDs().put(checkout.getID(), 0L);
}
io.saveCloudSettings(cloudSettings);
if (listener != null) {
listener.success(event);
}
}
use of com.cpjd.roblu.models.RCheckout in project Roblu by wdavies973.
the class Service method loop.
/**
* This is the main background service looper, this should perform any necessary
* Roblu Cloud sync operations
*/
public void loop() {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);
if (!Utils.hasInternetConnection(getApplicationContext())) {
Log.d("RBS", "No internet connection detected. Ending loop() early.");
return;
}
/*
* Create all the utilities we need for this loop
*/
IO io = new IO(getApplicationContext());
RSettings settings = io.loadSettings();
RSyncSettings cloudSettings = io.loadCloudSettings();
Request r = new Request(settings.getServerIP());
ObjectMapper mapper = new ObjectMapper().configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
CloudTeamRequest teamRequest = new CloudTeamRequest(r, settings.getCode());
CloudCheckoutRequest checkoutRequest = new CloudCheckoutRequest(r, settings.getCode());
boolean result = r.ping();
if (result)
Utils.requestServerHealthRefresh(getApplicationContext(), "online");
else
Utils.requestServerHealthRefresh(getApplicationContext(), "offline");
if (!result) {
Log.d("RBS", "Roblu server is down. Unable to connect.");
return;
}
// Load the active event
REvent[] events = io.loadEvents();
REvent activeEvent = null;
for (int i = 0; events != null && events.length > 0 && i < events.length; i++) {
if (events[i].isCloudEnabled()) {
activeEvent = events[i];
break;
}
}
if (activeEvent != null && activeEvent.getReadOnlyTeamNumber() != -1) {
teamRequest.setTeamNumber(activeEvent.getReadOnlyTeamNumber());
teamRequest.setCode("");
checkoutRequest.setTeamNumber(activeEvent.getReadOnlyTeamNumber());
checkoutRequest.setTeamCode("");
}
/*
* Check if a purge is requested
*/
if (cloudSettings.isPurgeRequested() && checkoutRequest.purge()) {
cloudSettings.setPurgeRequested(false);
cloudSettings.setTeamSyncID(0);
cloudSettings.getCheckoutSyncIDs().clear();
Log.d("RBS", "Event successfully purged from Roblu Cloud.");
io.saveCloudSettings(cloudSettings);
Notify.notifyNoAction(getApplicationContext(), "Event purged", "Active event successfully removed from Roblu Cloud.");
return;
}
if (activeEvent == null)
return;
// Create the sync helper
SyncHelper syncHelper = new SyncHelper(getApplicationContext(), activeEvent, SyncHelper.MODES.NETWORK);
RForm form = io.loadForm(activeEvent.getID());
/*
* Check to see if the form was modified and needs to be uploaded
*/
if (form.isUploadRequired()) {
try {
teamRequest.pushForm(mapper.writeValueAsString(form));
form.setUploadRequired(false);
io.saveForm(activeEvent.getID(), form);
Notify.notifyNoAction(getApplicationContext(), "Form uploaded", "Successfully uploaded RForm to the server.");
Log.d("RBS-Service", "Successfully uploaded RForm to the server.");
} catch (Exception e) {
Log.d("RBS-Service", "Failed to complete an upload required request for RForm.");
}
}
/*
* Check to see if the UI model should be uploaded
*/
if (settings.getRui().isUploadRequired()) {
try {
teamRequest.pushUI(mapper.writeValueAsString(settings.getRui()));
settings.getRui().setUploadRequired(false);
io.saveSettings(settings);
Log.d("RBS-Service", "Successfully uploaded RUI to the server.");
} catch (Exception e) {
Log.d("RBS-Service", "Failed to complete an upload required request for RUI.");
}
}
/*
* Check for cloud team updates
*/
try {
CloudTeam t = teamRequest.getTeam(cloudSettings.getTeamSyncID());
if (t != null) {
/*
* If a different master app overwrites the cloud app with a different event, run this check to prevent conflicts
* from happening.
*/
if (t.getActiveEventName() != null && !t.getActiveEventName().equals("") && activeEvent.getName() != null && !t.getActiveEventName().equals(activeEvent.getName())) {
activeEvent.setCloudEnabled(false);
cloudSettings.getCheckoutSyncIDs().clear();
io.saveCloudSettings(cloudSettings);
io.saveEvent(activeEvent);
return;
}
// Merge RForm
form = mapper.readValue(t.getForm(), RForm.class);
form.setUploadRequired(false);
io.saveForm(activeEvent.getID(), form);
// Merge RUI
RUI rui = mapper.readValue(t.getUi(), RUI.class);
rui.setUploadRequired(false);
settings.setRui(rui);
// make sure to refresh this
settings = io.loadSettings();
io.saveSettings(settings);
// Update the sync ID
cloudSettings.setTeamSyncID((int) t.getSyncID());
io.saveCloudSettings(cloudSettings);
Log.d("RBS-Service", "Successfully pulled team data from the server.");
}
} catch (Exception e) {
Log.d("RBS-Service", "Failed to pull team data from the server: " + e.getMessage());
}
/*
*
* Alright, into the belly of the beast.
* This code will check for completed checkouts on the server and merge them with the local repository.
* Shall we begin?
*
*/
try {
CloudCheckout[] checkouts = checkoutRequest.pullCompletedCheckouts(syncHelper.packSyncIDs(cloudSettings.getCheckoutSyncIDs()));
syncHelper.unpackCheckouts(checkouts, cloudSettings);
io.saveCloudSettings(cloudSettings);
} catch (Exception e) {
Log.d("RBS-Service", "An error occurred while fetching completed checkouts. " + e.getMessage());
}
/*
* Next, uploading everything from /pending/
*/
try {
Log.d("RBS-Service", "Checking for any checkouts to upload...");
ArrayList<RCheckout> checkouts = new ArrayList<>(Arrays.asList(io.loadPendingCheckouts()));
boolean wasSuccess = checkoutRequest.pushCheckouts(syncHelper.packCheckouts(checkouts));
if (wasSuccess) {
for (RCheckout checkout : checkouts) {
io.deletePendingCheckout(checkout.getID());
}
Notify.notifyNoAction(getApplicationContext(), "Uploaded new checkouts", "Uploaded " + checkouts.size() + " new checkout(s).");
}
Log.d("RBS-Service", "Uploaded " + checkouts.size() + " checkouts.");
} catch (Exception e) {
Log.d("RBS-Service", "An error occurred while attempting to push /pending/ checkouts: " + e.getMessage());
}
io.saveCloudSettings(cloudSettings);
Log.d("RBS-Service", "Sleeping Roblu background service for 10 seconds...");
}
use of com.cpjd.roblu.models.RCheckout in project Roblu by wdavies973.
the class CheckoutEncoder method decodeCheckout.
/**
* Decodes a checkout encoded in the CheckoutEncoder format
* @param string the string to deserialize
* @return an instantiated checkout from the string
*/
public RCheckout decodeCheckout(String string) {
try {
String[] lines = string.split("\n");
for (String s : lines) {
Log.d("RBS", "Line: " + s);
}
// Meta
RCheckout checkout = new RCheckout();
checkout.setID(Integer.parseInt(lines[0]));
checkout.setNameTag(lines[1]);
RTeam team = new RTeam();
team.setID(Integer.parseInt(lines[2]));
team.setLastEdit(Long.parseLong(lines[3]));
team.setTabs(new ArrayList<RTab>());
// Tabs
for (int i = 0; i < lines.length; i++) {
if (!lines[i].startsWith("TAB"))
continue;
// Tab meta
RTab tab = new RTab();
tab.setTitle(lines[i].substring(3));
tab.setWon(Boolean.parseBoolean(lines[i + 1]));
tab.setMetrics(new ArrayList<RMetric>());
String[] tokens = lines[i + 2].split(",");
LinkedHashMap<String, Long> edits = new LinkedHashMap<>();
for (int k = 1; k < tokens.length; k++) {
edits.put(tokens[1], Long.parseLong(tokens[2]));
}
tab.setEdits(edits);
// Metrics
for (int k = i + 1; k < lines.length; k++) {
if (lines[k].startsWith("TAB"))
break;
if (lines[i].startsWith("null"))
continue;
String[] mTokens = lines[k].split(String.valueOf(DELIMITER));
RMetric metric = null;
switch(mTokens[0]) {
case // boolean
"B":
metric = new RBoolean();
((RBoolean) metric).setValue(Boolean.parseBoolean(mTokens[4]));
break;
case "CH":
{
// checkbox
metric = new RCheckbox();
LinkedHashMap<String, Boolean> values = new LinkedHashMap<>();
for (int l = 4; l < mTokens.length; l++) {
values.put(mTokens[l].split(",")[0].substring(1), Boolean.parseBoolean(mTokens[l].split(",")[1].replace(")", "")));
}
((RCheckbox) metric).setValues(values);
break;
}
case "CO":
{
// chooser
metric = new RChooser();
((RChooser) metric).setSelectedIndex(Integer.parseInt(mTokens[4]));
// the amount of values, with the header info removed
String[] values = new String[mTokens.length - 6];
for (int l = 5; l < mTokens.length - 1; l++) {
if (mTokens[l] != null && !mTokens[l].equals(""))
values[l - 5] = mTokens[l];
}
((RChooser) metric).setValues(values);
break;
}
case // counter
"C":
metric = new RCounter();
((RCounter) metric).setVerboseInput(Boolean.parseBoolean(mTokens[4]));
((RCounter) metric).setValue(Double.parseDouble(mTokens[5]));
((RCounter) metric).setIncrement(Double.parseDouble(mTokens[6]));
break;
case // slider
"S":
metric = new RSlider();
((RSlider) metric).setValue(Integer.parseInt(mTokens[4]));
((RSlider) metric).setMin(Integer.parseInt(mTokens[5]));
((RSlider) metric).setMax(Integer.parseInt(mTokens[6]));
break;
case // stopwatch
"ST":
metric = new RStopwatch();
((RStopwatch) metric).setTime(Double.parseDouble(mTokens[4]));
((RStopwatch) metric).setTimes(new ArrayList<Double>());
for (int l = 5; l < mTokens.length; l++) {
if (!mTokens[l].equals(""))
((RStopwatch) metric).getTimes().add(Double.parseDouble(mTokens[5]));
}
break;
case // textfield
"T":
metric = new RTextfield();
((RTextfield) metric).setText((mTokens[4]));
break;
}
if (metric != null) {
metric.setID(Integer.parseInt(mTokens[1]));
metric.setTitle(mTokens[2]);
metric.setModified(Boolean.parseBoolean(mTokens[3]));
tab.getMetrics().add(metric);
// Adding metric
Log.d("RBS", "Adding metric " + metric.toString());
}
}
team.getTabs().add(tab);
}
checkout.setTeam(team);
return checkout;
} catch (Exception e) {
e.printStackTrace();
Log.d("RBS", "An error occurred while decoding a checkout. " + e.getMessage());
return null;
}
}
use of com.cpjd.roblu.models.RCheckout in project Roblu by wdavies973.
the class QrReader method onQRCodeRead.
// Called when a QR is decoded
// "text" : the text encoded in QR
// "points" : points where QR control points are placed in View
@Override
public void onQRCodeRead(final String text, PointF[] points) {
if (syncedAlready)
return;
if (!syncedAlready) {
syncedAlready = true;
}
Log.d("RBS", "QR Read: " + text);
/*
* Decompress and import the checkout
*/
new Thread(new Runnable() {
@Override
public void run() {
try {
/*
* Import the checkout!
*/
RCheckout checkout = new CheckoutEncoder().decodeCheckout(text);
new SyncHelper(getApplicationContext(), event, SyncHelper.MODES.QR).mergeCheckout(checkout);
// Flag for upload
// reload the team after merge
checkout.setTeam(new IO(getApplicationContext()).loadTeam(event.getID(), checkout.getTeam().getID()));
new IO(getApplicationContext()).savePendingCheckout(checkout);
Notify.notifyMerged(getApplicationContext(), event.getID(), checkout);
// close QR scanner
finish();
} catch (Exception e) {
Log.d("RBS", "Failed to import checkout from QR code: " + e.getMessage());
}
}
}).start();
}
Aggregations