├── benign └── app │ └── src │ ├── androidTest │ └── java │ │ └── wubbalubbadubdub │ │ └── benignhw1 │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── wubbalubbadubdub │ │ │ └── benignhw1 │ │ │ ├── AddEventActivity.java │ │ │ ├── ListActivity.java │ │ │ ├── SelectUserActivity.java │ │ │ ├── ViewActivity.java │ │ │ └── data │ │ │ ├── DBContract.java │ │ │ ├── DatabaseHelper.java │ │ │ ├── Event.java │ │ │ └── HelperMethods.java │ └── res │ │ ├── layout │ │ ├── activity_add_event.xml │ │ ├── activity_list.xml │ │ ├── activity_select_user.xml │ │ └── activity_view.xml │ │ ├── mipmap-hdpi │ │ ├── ic_benign_icon.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_benign_icon.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_benign_icon.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_benign_icon.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_benign_icon.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── wubbalubbadubdub │ └── benignhw1 │ └── ExampleUnitTest.java └── ransom └── app └── src ├── androidTest └── java │ └── wubbalubbadubdub │ └── hw1700ransomware │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── java │ └── wubbalubbadubdub │ │ └── hw1700ransomware │ │ ├── AddEventActivity.java │ │ ├── ListActivity.java │ │ ├── PayUp.java │ │ ├── SelectUserActivity.java │ │ ├── ViewActivity.java │ │ └── data │ │ ├── DBContract.java │ │ ├── DatabaseHelper.java │ │ ├── Event.java │ │ └── HelperMethods.java └── res │ ├── color │ └── textcolor2.xml │ ├── layout │ ├── activity_add_event.xml │ ├── activity_list.xml │ ├── activity_pay_up.xml │ ├── activity_select_user.xml │ └── activity_view.xml │ ├── mipmap-hdpi │ ├── ic_benign_icon.png │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── ic_malicious_icon.png │ ├── mipmap-mdpi │ ├── ic_benign_icon.png │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── ic_malicious_icon.png │ ├── mipmap-xhdpi │ ├── ic_benign_icon.png │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── ic_malicious_icon.png │ ├── mipmap-xxhdpi │ ├── ic_benign_icon.png │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── ic_malicious_icon.png │ ├── mipmap-xxxhdpi │ ├── ic_benign_icon.png │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ └── ic_malicious_icon.png │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── strings.xml │ └── styles.xml └── test └── java └── wubbalubbadubdub └── hw1700ransomware └── ExampleUnitTest.java /benign/app/src/androidTest/java/wubbalubbadubdub/benignhw1/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("wubbalubbadubdub.eecs448project1", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /benign/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/AddEventActivity.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.util.TypedValue; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | import android.widget.TableLayout; 11 | import android.widget.TableRow; 12 | import android.widget.TextView; 13 | import android.graphics.Color; 14 | import android.widget.DatePicker; 15 | import android.widget.DatePicker.OnDateChangedListener; 16 | import android.widget.Toast; 17 | 18 | 19 | import java.util.ArrayList; 20 | import java.util.Calendar; 21 | import java.util.List; 22 | 23 | 24 | import wubbalubbadubdub.benignhw1.data.DatabaseHelper; 25 | import wubbalubbadubdub.benignhw1.data.Event; 26 | import wubbalubbadubdub.benignhw1.data.HelperMethods; //For toTime() method 27 | 28 | /** 29 | * AddEventActivity.java 30 | * @author Dustin, Damian, Lane 31 | * @version 1.1 32 | * This Class allows the user to create an event and select timeslots for the event created 33 | */ 34 | public class AddEventActivity extends Activity { 35 | 36 | private DatabaseHelper dbHelper; 37 | private Toast statusMessage; 38 | 39 | private String currentUser; 40 | private List selectedTimeslots; 41 | private boolean format = false; //Time format: false=12h | true=24h 42 | 43 | //Color Variables - Material Design 44 | int BLUE_MAT = Color.rgb(2,136,209); 45 | int GREEN_MAT = Color.rgb(139,195,74); 46 | 47 | /** 48 | * Method called when the activity is first created. Lots of formatting done. 49 | * @param savedInstanceState Unused Bundle object. Usually used if the app is killed then we can resume 50 | */ 51 | @Override 52 | protected void onCreate(Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | setContentView(R.layout.activity_add_event); 55 | 56 | dbHelper = new DatabaseHelper(getApplicationContext()); 57 | statusMessage = Toast.makeText(this, "", Toast.LENGTH_SHORT); 58 | 59 | Intent intent = getIntent(); 60 | currentUser = intent.getStringExtra("currentUser"); 61 | 62 | TextView welcome = (TextView) findViewById(R.id.tvWelcome); 63 | welcome.setText(currentUser + ", create your event"); 64 | selectedTimeslots = new ArrayList<>(); 65 | 66 | createTimeslotTable(); 67 | 68 | //Set Date Picker to current date, datePicker constraints etc. 69 | int[] date = HelperMethods.getCurrentDate(); 70 | DatePicker datePicker = (DatePicker) findViewById(R.id.datePicker); 71 | int month = date[0]; 72 | int day = date[1]; 73 | int year = date[2]; 74 | 75 | //Now set the default date to today thru this init method I found 76 | datePicker.init(year, month, day, new OnDateChangedListener() { 77 | @Override 78 | public void onDateChanged(DatePicker dp, int y, int m, int d) { 79 | //clearTimeslotTable(); ENABLE TO RESET TIMESLOTS UPON DATE SWITCH 80 | } 81 | }); 82 | 83 | datePicker.setMinDate(System.currentTimeMillis() - 1000); 84 | Calendar max = Calendar.getInstance(); 85 | max.set(Calendar.YEAR, 2100); 86 | 87 | datePicker.setMaxDate((max.getTime()).getTime()); 88 | 89 | 90 | } 91 | 92 | /** 93 | * This function will create the table of buttons to select an event's timeframe 94 | */ 95 | private void createTimeslotTable() { 96 | TableLayout layout = (TableLayout) findViewById(R.id.tbLayout); 97 | 98 | int count = 0; 99 | for (int i = 0; i < 4; i++) { 100 | TableRow tr = new TableRow(this); 101 | for (int j = 0; j < 12; j++) { 102 | final int current = count; 103 | Button b = new Button(this); 104 | b.setText(HelperMethods.toTime(count,format)); 105 | b.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); 106 | b.setTransformationMethod(null); 107 | TableRow.LayoutParams cellParams = new TableRow.LayoutParams(); 108 | cellParams.rightMargin = 5; 109 | b.setLayoutParams(cellParams); 110 | b.setBackgroundColor(GREEN_MAT); 111 | b.setOnClickListener(new Button.OnClickListener() { 112 | int id = current; 113 | boolean selected = false; 114 | 115 | @Override 116 | public void onClick(View v) { 117 | Button obj = (Button) v; 118 | if (selected) { 119 | obj.setBackgroundColor(GREEN_MAT); 120 | selectedTimeslots.remove(Integer.valueOf(id)); 121 | } else { 122 | obj.setBackgroundColor(BLUE_MAT); 123 | selectedTimeslots.add(id); 124 | } 125 | selected = !selected; 126 | updateTimeDisplay(); 127 | } 128 | }); 129 | tr.addView(b); 130 | count++; 131 | } 132 | TableLayout.LayoutParams tableRowParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT); 133 | 134 | tableRowParams.setMargins(10, 2, 10, 2); 135 | 136 | tr.setLayoutParams(tableRowParams); 137 | 138 | 139 | layout.addView(tr, tableRowParams); 140 | } 141 | } 142 | 143 | /** 144 | * clear timeslot table - originally wrote for onDateChangedListener, realized it's probably 145 | * unnecessary but keeping it in case we want it for anything else, e.g. a 'clear times' button 146 | */ 147 | private void clearTimeslotTable() { 148 | 149 | selectedTimeslots.clear(); 150 | 151 | TableLayout tableLayout = (TableLayout) findViewById(R.id.tbLayout); 152 | int count = 0; 153 | for (int i = 0; i < 4; i++) { 154 | TableRow row = (TableRow)tableLayout.getChildAt(i); 155 | for (int j = 0; j < 12; j++) { 156 | Button b = (Button) row.getChildAt(j); 157 | b.setBackgroundColor(GREEN_MAT); 158 | count++; 159 | } 160 | } 161 | updateTimeDisplay(); 162 | 163 | } 164 | 165 | /** 166 | * This function is called when the 12h/24h toggle button is pressed 167 | * @param v View of the pressed button 168 | */ 169 | public void toggleFormat(View v) { 170 | TableLayout tableLayout = (TableLayout) findViewById(R.id.tbLayout); 171 | 172 | format = !format; 173 | 174 | int count = 0; 175 | for (int i = 0; i < 4; i++) { 176 | TableRow row = (TableRow)tableLayout.getChildAt(i); 177 | for (int j = 0; j < 12; j++) { 178 | Button b = (Button) row.getChildAt(j); 179 | b.setText(HelperMethods.toTime(count, format)); 180 | count++; 181 | } 182 | } 183 | updateTimeDisplay(); 184 | 185 | } 186 | 187 | /** 188 | * Updates the Selected timeframe for the event 189 | */ 190 | private void updateTimeDisplay() { 191 | TextView timeDisplay = (TextView) findViewById(R.id.tvSelectedTimes); 192 | 193 | String disp = "Event Timeframe: " + HelperMethods.getTimeString(selectedTimeslots, format); 194 | 195 | if (selectedTimeslots.isEmpty()) disp = "PLEASE SELECT TIMES"; 196 | 197 | timeDisplay.setText(disp); 198 | } 199 | 200 | /** 201 | * Verifies that the Event is valid before attempting to insert to the database 202 | * @param e Event object of the event to be created. 203 | * @return True if valid, false otherwise 204 | */ 205 | boolean verify(Event e) { 206 | 207 | //Dates should have no way of being invalid 208 | 209 | //Name verification 210 | if (e.getName().isEmpty()) { 211 | statusMessage.setText("ERROR: Please name your event!"); 212 | return false; 213 | } 214 | 215 | //Timeslot verification 216 | if (e.getTimeslots().isEmpty()) { 217 | statusMessage.setText("ERROR: Please choose times for your event!"); 218 | return false; 219 | } 220 | 221 | //Check if user is already signed up for any conflicting events 222 | /*pseudo: if intersection of (currentuser.signups.timeslots) list with (e.timeslots) list 223 | * is nonempty, -> conflict found, return false*/ 224 | 225 | return true; 226 | } 227 | 228 | /** 229 | * onSaveButtonClick() - Handles Save button - creates event object, verifies, and adds event 230 | * @param v View of the button that was pressed 231 | */ 232 | public void onSaveButtonClick(View v) { 233 | 234 | //Build date string for event 235 | DatePicker datePicker = (DatePicker) findViewById(R.id.datePicker); 236 | int month = datePicker.getMonth() + 1; 237 | int day = datePicker.getDayOfMonth(); 238 | int year = datePicker.getYear(); 239 | String date = HelperMethods.dateToString(month, day, year); 240 | 241 | //Get name of event 242 | EditText nameText = (EditText) findViewById(R.id.textName); 243 | String name = nameText.getText().toString(); 244 | 245 | //Stringify timeslot list in int format for storage in db 246 | String timeslotIntList = HelperMethods.stringifyTimeslotInts(selectedTimeslots); 247 | 248 | //Create an event, attempt to verify it, and send to db if all is well 249 | /*Event ID is set to -1 because it's useless until a real ID is assigned 250 | *by the primary key upon insertion to the database after successful verification.*/ 251 | Event e = new Event(-1, date, name, currentUser, timeslotIntList); 252 | 253 | if (verify(e)){ 254 | 255 | //Add event and automatically sign creator up for duration of event 256 | int eventID = dbHelper.addEvent(e); 257 | dbHelper.addSignup(eventID, currentUser, selectedTimeslots); 258 | 259 | statusMessage.setText("Your event has been created."); 260 | statusMessage.show(); 261 | Intent intent = new Intent(getApplicationContext(), ListActivity.class); 262 | intent.putExtra("currentUser", currentUser); 263 | finish(); 264 | startActivity(intent); 265 | 266 | }else statusMessage.show(); 267 | } 268 | 269 | 270 | } 271 | -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/ListActivity.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.graphics.Color; 6 | import android.graphics.Typeface; 7 | import android.os.Bundle; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.TableLayout; 11 | import android.widget.TableRow; 12 | import android.widget.TextView; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | 17 | import wubbalubbadubdub.benignhw1.data.DatabaseHelper; 18 | import wubbalubbadubdub.benignhw1.data.Event; 19 | import wubbalubbadubdub.benignhw1.data.HelperMethods; 20 | 21 | /** 22 | * This page list all the activities created by other users. 23 | * Also this page allows the user to add an event which brings them to the AddEvent page 24 | * @author Dustin, Lane, Damian 25 | * @version 1.0 26 | */ 27 | public class ListActivity extends Activity { 28 | 29 | private DatabaseHelper dbHelper; 30 | private String currentUser; 31 | private boolean format = false; //Time formatting boolean 32 | 33 | final int DARK_CYAN = Color.rgb(0, 151, 167); 34 | final int BLUE_MAT = Color.rgb(2,136,209); //For dolling up the event titles 35 | final int LIGHT_BG = Color.rgb(201, 221, 255); 36 | final int DARK_BG = Color.rgb(153, 192, 255); 37 | 38 | private boolean allEvents = true; //Determines whether to show all events or own events 39 | 40 | @Override 41 | protected void onCreate(Bundle savedInstanceState) { 42 | 43 | super.onCreate(savedInstanceState); 44 | setContentView(R.layout.activity_list); 45 | 46 | dbHelper = new DatabaseHelper(getApplicationContext()); 47 | 48 | Intent intent = getIntent(); 49 | currentUser = intent.getStringExtra("currentUser"); 50 | TextView welcomeText = (TextView) findViewById(R.id.tvWelcome); 51 | welcomeText.setText("Hello " + currentUser + "!"); 52 | 53 | populateEventTable(); 54 | 55 | } 56 | 57 | /** 58 | * Handles All Events toggle button 59 | * @param v - (Given view) 60 | */ 61 | public void toggleEventList(View v) { 62 | allEvents = !allEvents; 63 | populateEventTable(); 64 | } 65 | 66 | /** 67 | * Toggles time formatting in table 68 | * @param v - (Given view) 69 | */ 70 | public void toggleFormat(View v) { 71 | format = !format; 72 | populateEventTable(); 73 | } 74 | 75 | /** 76 | * Populates event table 77 | */ 78 | private void populateEventTable() { 79 | TableLayout layout = (TableLayout) findViewById(R.id.eventTableLayout); 80 | TableLayout.LayoutParams tableRowParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT); 81 | 82 | //Clears the table before (re)populating 83 | for (int i = 0; i < layout.getChildCount(); i++) { 84 | View row = layout.getChildAt(i); 85 | if (row instanceof TableRow) ((ViewGroup) row).removeAllViews(); 86 | layout.removeAllViews(); 87 | } 88 | 89 | tableRowParams.setMargins(10, 2, 10, 2); 90 | ArrayList events = (allEvents) ? dbHelper.getAllEvents() : dbHelper.getUserEvents(currentUser); 91 | Collections.sort(events); 92 | 93 | int numberOfEvents = events.size(); 94 | int rowBG = 1; 95 | 96 | //Title row creation 97 | TableRow titleRow = new TableRow(this); 98 | titleRow.setBackgroundColor(DARK_CYAN); 99 | 100 | TableRow.LayoutParams titleLayout = new TableRow.LayoutParams(); 101 | titleLayout.setMargins(0, 10, 10, 15); 102 | 103 | TextView titleName = new TextView(this); 104 | TextView titleCreator = new TextView(this); 105 | TextView titleDay = new TextView(this); 106 | TextView titleTimeslots = new TextView(this); 107 | 108 | titleCreator.setLayoutParams(titleLayout); 109 | titleName.setLayoutParams(titleLayout); 110 | titleDay.setLayoutParams(titleLayout); 111 | titleTimeslots.setLayoutParams(titleLayout); 112 | 113 | titleName.setPadding(3, 10, 0, 10); 114 | titleCreator.setPadding(0, 10, 0, 10); 115 | titleDay.setPadding(0, 10, 0, 10); 116 | titleTimeslots.setPadding(0, 10, 0, 10); 117 | 118 | titleName.setText("Event Name"); 119 | titleCreator.setText("Creator"); 120 | titleDay.setText("Date"); 121 | titleTimeslots.setText("Scheduled Times"); 122 | 123 | titleName.setTextSize(18); 124 | titleCreator.setTextSize(18); 125 | titleDay.setTextSize(18); 126 | titleDay.setTextSize(18); 127 | titleTimeslots.setTextSize(18); 128 | 129 | titleName.setTypeface(null, Typeface.BOLD); 130 | titleCreator.setTypeface(null, Typeface.BOLD); 131 | titleDay.setTypeface(null, Typeface.BOLD); 132 | titleTimeslots.setTypeface(null, Typeface.BOLD); 133 | 134 | titleRow.addView(titleName); 135 | titleRow.addView(titleCreator); 136 | titleRow.addView(titleDay); 137 | titleRow.addView(titleTimeslots); 138 | 139 | layout.addView(titleRow, tableRowParams); 140 | 141 | 142 | //Generate rest of event rows 143 | for (int i = 0; i < numberOfEvents; i++) { 144 | TableRow row = new TableRow(this); 145 | 146 | row.setBackgroundColor((rowBG % 2 == 1) ? LIGHT_BG : DARK_BG); 147 | 148 | Event workingEvent = events.get(i); 149 | 150 | TableRow.LayoutParams tvLayout = new TableRow.LayoutParams(); 151 | tvLayout.setMargins(0, 10, 10, 15); 152 | 153 | TextView eventName = new TextView(this); 154 | TextView eventCreator = new TextView(this); 155 | TextView eventDay = new TextView(this); 156 | TextView eventTimeslots = new TextView(this); 157 | 158 | eventName.setLayoutParams(tvLayout); 159 | eventCreator.setLayoutParams(tvLayout); 160 | eventDay.setLayoutParams(tvLayout); 161 | eventTimeslots.setLayoutParams(tvLayout); 162 | 163 | eventName.setPadding(3, 10, 0, 10); 164 | eventCreator.setPadding(0, 10, 0, 10); 165 | eventDay.setPadding(0, 10, 0, 10); 166 | eventTimeslots.setPadding(10, 10, 0, 10); 167 | 168 | eventName.setTextSize(20); 169 | eventName.setTypeface(null, Typeface.BOLD); 170 | eventName.setTextColor(BLUE_MAT); 171 | eventCreator.setTextSize(20); 172 | eventDay.setTextSize(20); 173 | eventTimeslots.setTextSize(20); 174 | 175 | //Prettier formatting, convert timeslots into timestring through series of parsing methods 176 | eventCreator.setText(workingEvent.getCreator()); 177 | eventDay.setText(workingEvent.getDate()); 178 | eventName.setText(workingEvent.getName()); 179 | eventTimeslots.setText(HelperMethods.getTimeString(HelperMethods.listifyTimeslotInts(workingEvent.getTimeslots()), format)); 180 | 181 | row.addView(eventName); 182 | row.addView(eventCreator); 183 | row.addView(eventDay); 184 | row.addView(eventTimeslots); 185 | 186 | row.setLayoutParams(tableRowParams); 187 | 188 | final int workingEventID = workingEvent.getID(); 189 | 190 | row.setOnClickListener(new View.OnClickListener() { 191 | int id = workingEventID; 192 | 193 | @Override 194 | public void onClick(View view) { 195 | Intent intent = new Intent(getApplicationContext(), ViewActivity.class); 196 | intent.putExtra("currentUser", currentUser); 197 | intent.putExtra("eventID", id); 198 | 199 | startActivity(intent); 200 | } 201 | }); 202 | 203 | 204 | layout.addView(row, tableRowParams); 205 | rowBG++; 206 | 207 | } 208 | } 209 | 210 | /** 211 | * Handles Add new Event button 212 | * @param v - (given view) 213 | */ 214 | public void newEvent(View v) { 215 | Intent intent = new Intent(this, AddEventActivity.class); 216 | intent.putExtra("currentUser", currentUser); 217 | finish(); 218 | startActivity(intent); 219 | } 220 | 221 | 222 | } 223 | -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/SelectUserActivity.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.text.TextUtils; 7 | import android.view.View; 8 | import android.widget.AdapterView; 9 | import android.widget.ArrayAdapter; 10 | import android.widget.EditText; 11 | import android.widget.ListView; 12 | import android.widget.Toast; 13 | 14 | import java.util.List; 15 | 16 | import wubbalubbadubdub.benignhw1.data.DatabaseHelper; 17 | 18 | /** 19 | * This is the starting activity for our application. Here the user will select or add users 20 | * @author Damian, Lane 21 | * @version 1.0 22 | */ 23 | public class SelectUserActivity extends Activity { 24 | private DatabaseHelper dbHelper; 25 | private Toast statusMessage; 26 | private ListView userList; 27 | 28 | /** 29 | * This function is called when the activity is first created 30 | * @param savedInstanceState Every oncreate needs this. Allows to revert to previous state 31 | * @since 1.0 32 | */ 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_select_user); 37 | 38 | dbHelper = new DatabaseHelper(getApplicationContext()); 39 | statusMessage = Toast.makeText(this, "", Toast.LENGTH_SHORT); 40 | 41 | userList = (ListView) findViewById(R.id.lvUsers); 42 | userList.setOnItemClickListener(new AdapterView.OnItemClickListener() { 43 | @Override 44 | public void onItemClick(AdapterView parent, View view, int position, long id) { 45 | String selectedUser = userList.getItemAtPosition(position).toString(); 46 | 47 | Intent intent = new Intent(getApplicationContext(), ListActivity.class); 48 | intent.putExtra("currentUser", selectedUser); 49 | startActivity(intent); 50 | } 51 | }); 52 | populateUsers(); 53 | } 54 | 55 | /** 56 | * This function utilizes the DatabaseHelper class to populate a listview with all users 57 | * in the database 58 | * @since 1.0 59 | */ 60 | private void populateUsers() { 61 | List users = dbHelper.getUsers(); 62 | 63 | ArrayAdapter arrayAdapter = new ArrayAdapter( 64 | this, 65 | android.R.layout.simple_list_item_1, 66 | users ); 67 | 68 | userList.setAdapter(arrayAdapter); 69 | } 70 | 71 | /** 72 | * This function will utilize the DatabaseHelper to add a new user 73 | * @param v The View that fired the addUser() function. In this case it is the addUserButton 74 | * @since 1.0 75 | */ 76 | public void addUser(View v) { 77 | EditText textbox = (EditText) findViewById(R.id.newUsername); 78 | String name = textbox.getText().toString().trim(); //removes any lead/trailing spaces as well 79 | 80 | 81 | if (isValidName(name)) statusMessage.setText(name + " was added to the list of users"); 82 | statusMessage.show(); 83 | populateUsers(); 84 | } 85 | 86 | /** 87 | * 88 | * @param name the string to check the validity of 89 | * @return false if the name contains invalid characters 90 | * @since 1.0 91 | */ 92 | private boolean isValidName(String name) { 93 | 94 | //Conditions for valid username creation 95 | if (TextUtils.isEmpty(name)){ //Empty name 96 | statusMessage.setText("ERROR: Please input a name for the new user"); 97 | return false; 98 | } else if (!name.matches("[a-zA-Z\\s]+")) { //Non a-z characters in name 99 | statusMessage.setText("ERROR: Name contains invalid characters"); 100 | return false; 101 | } else if (dbHelper.addUser(name) == -1) { //name already exists 102 | statusMessage.setText("ERROR: That Username already exists!"); 103 | return false; 104 | }else return true; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/ViewActivity.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.graphics.Color; 6 | import android.graphics.Typeface; 7 | import android.os.Bundle; 8 | import android.util.TypedValue; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.Button; 12 | import android.widget.TableLayout; 13 | import android.widget.TableRow; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | import wubbalubbadubdub.benignhw1.data.DatabaseHelper; 22 | import wubbalubbadubdub.benignhw1.data.Event; 23 | import wubbalubbadubdub.benignhw1.data.HelperMethods; 24 | 25 | /** 26 | * This activity is for viewing a certain activity. 27 | * The view will be different dependent on if the Current user was the creator of the event 28 | * @author Dustin, Lane, Damian 29 | * @version 1.0 30 | */ 31 | public class ViewActivity extends Activity { 32 | 33 | DatabaseHelper dbHelper; 34 | 35 | Boolean format = false; 36 | 37 | private int currentID; 38 | private String currentUser; 39 | private Event currentEvent; 40 | 41 | private List currentTimeslots; 42 | private List selectedTimeslots; 43 | 44 | private int selectedRow = -1; 45 | private int selectedSlot = -1; 46 | 47 | private Map userSignups; 48 | 49 | private Toast statusMessage; 50 | 51 | private boolean prevSignup; 52 | 53 | private boolean adminMode; 54 | 55 | //Color Variables - Material Design 56 | int BLUE_MAT = Color.rgb(2,136,209); 57 | int GREEN_MAT = Color.rgb(139,195,74); 58 | 59 | /** 60 | * Method called when the activity is first created and displayed to the screen 61 | * @param savedInstanceState Unused Bundle object. Usually used if the app is killed then we can resume 62 | */ 63 | @Override 64 | protected void onCreate(Bundle savedInstanceState) { 65 | super.onCreate(savedInstanceState); 66 | setContentView(R.layout.activity_view); 67 | 68 | Intent intent = getIntent(); 69 | currentID = intent.getIntExtra("eventID", -1); 70 | currentUser = intent.getStringExtra("currentUser"); 71 | 72 | statusMessage = Toast.makeText(this, "", Toast.LENGTH_SHORT); 73 | 74 | 75 | dbHelper = new DatabaseHelper(getApplicationContext()); 76 | 77 | currentEvent = dbHelper.getEvent(currentID); 78 | 79 | adminMode = currentUser.equals(currentEvent.getCreator()); 80 | 81 | String creatorString = "Created by: " + currentEvent.getCreator(); 82 | String eventString = currentEvent.getName() + " - " + ((adminMode) ? "Admin Mode" : "Select Availability"); 83 | 84 | TextView eventName = (TextView) findViewById(R.id.tvEventName); 85 | TextView eventCreator = (TextView) findViewById(R.id.tvCreator); 86 | TextView eventDate = (TextView) findViewById(R.id.tvDate); 87 | 88 | eventName.setText(eventString); 89 | eventCreator.setText(creatorString); 90 | eventDate.setText(currentEvent.getDate()); 91 | 92 | currentTimeslots = HelperMethods.listifyTimeslotInts(currentEvent.getTimeslots()); 93 | selectedTimeslots = new ArrayList<>(); 94 | 95 | 96 | updateTimeframe(); 97 | 98 | userSignups = dbHelper.getSignups(currentID); 99 | 100 | prevSignup = userSignups.containsKey(currentUser); 101 | 102 | 103 | 104 | if (adminMode) { 105 | // View event status 106 | displayEventSignups(); 107 | 108 | ((Button)findViewById(R.id.btnSave)).setVisibility(View.GONE); 109 | } else { 110 | // Set availability 111 | 112 | ((TextView)findViewById(R.id.tvSelectedUser)).setVisibility(View.GONE); 113 | populateTimeslotTable(); 114 | } 115 | 116 | } 117 | 118 | /** 119 | * This method fills the timeslot table with the timeslots local to the current event 120 | */ 121 | private void populateTimeslotTable() { 122 | TableLayout layout = (TableLayout) findViewById(R.id.tbLayout); 123 | 124 | // Clear table 125 | for (int i = 0; i < layout.getChildCount(); i++) { 126 | View row = layout.getChildAt(i); 127 | if (row instanceof TableRow) ((ViewGroup) row).removeAllViews(); 128 | layout.removeAllViews(); 129 | } 130 | 131 | List currentUserSelection = (prevSignup) ? HelperMethods.listifyTimeslotInts(userSignups.get(currentUser)) : null; 132 | 133 | if (prevSignup) selectedTimeslots = currentUserSelection; 134 | 135 | int count = 0; 136 | for (int i = 0; i < 4; i++) { 137 | TableRow tr = new TableRow(this); 138 | for (int j = 0; j < 12; j++) { 139 | final int current = count; 140 | Button b = new Button(this); 141 | b.setText(HelperMethods.toTime(count,format)); 142 | b.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); 143 | TableRow.LayoutParams cellParams = new TableRow.LayoutParams(); 144 | cellParams.rightMargin = 5; 145 | b.setLayoutParams(cellParams); 146 | if (currentTimeslots.contains(count)) { 147 | boolean intSelect = false; 148 | if (currentUserSelection != null && currentUserSelection.contains(count)) { 149 | intSelect = true; 150 | b.setBackgroundColor(BLUE_MAT); 151 | } else { 152 | b.setBackgroundColor(GREEN_MAT); 153 | } 154 | final boolean select = intSelect; 155 | 156 | b.setOnClickListener(new Button.OnClickListener() { 157 | int id = current; 158 | boolean selected = select; 159 | 160 | @Override 161 | public void onClick(View v) { 162 | Button obj = (Button) v; 163 | if (selected) { 164 | obj.setBackgroundColor(GREEN_MAT); 165 | selectedTimeslots.remove(Integer.valueOf(id)); 166 | } else { 167 | obj.setBackgroundColor(BLUE_MAT); 168 | selectedTimeslots.add(id); 169 | } 170 | selected = !selected; 171 | updateTimeDisplay(); 172 | } 173 | }); 174 | } else { 175 | b.setBackgroundColor(Color.DKGRAY); 176 | } 177 | tr.addView(b); 178 | count++; 179 | } 180 | TableLayout.LayoutParams tableRowParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT); 181 | 182 | tableRowParams.setMargins(10, 2, 10, 2); 183 | 184 | tr.setLayoutParams(tableRowParams); 185 | 186 | layout.addView(tr, tableRowParams); 187 | } 188 | updateTimeDisplay(); 189 | } 190 | 191 | /** 192 | * This method displays the Event timeframe and which users are signed up 193 | */ 194 | private void displayEventSignups() { 195 | TableLayout layout = (TableLayout) findViewById(R.id.tbLayout); 196 | 197 | TableRow header = new TableRow(this); 198 | 199 | 200 | // Clear table 201 | for (int i = 0; i < layout.getChildCount(); i++) { 202 | View row = layout.getChildAt(i); 203 | if (row instanceof TableRow) ((ViewGroup) row).removeAllViews(); 204 | layout.removeAllViews(); 205 | } 206 | 207 | 208 | TableRow.LayoutParams cellParams = new TableRow.LayoutParams(); 209 | cellParams.setMargins(20, 20, 20, 20); 210 | 211 | TextView userHeader = new TextView(this); 212 | userHeader.setText("User"); 213 | userHeader.setTextSize(15); 214 | userHeader.setTypeface(null, Typeface.BOLD); 215 | userHeader.setLayoutParams(cellParams); 216 | header.addView(userHeader); 217 | 218 | for (int slot : currentTimeslots) { 219 | TextView slotHeader = new TextView(this); 220 | slotHeader.setText(HelperMethods.toTime(slot, format)); 221 | slotHeader.setTextSize(15); 222 | slotHeader.setTypeface(null, Typeface.BOLD); 223 | slotHeader.setLayoutParams(cellParams); 224 | final int thisSlot = slot; 225 | 226 | slotHeader.setOnClickListener(new View.OnClickListener() { 227 | int slot = thisSlot; 228 | 229 | @Override 230 | public void onClick(View view) { 231 | selectedRow = -1; 232 | selectedSlot = slot; 233 | 234 | highlightSelection(); 235 | 236 | } 237 | }); 238 | 239 | header.addView(slotHeader); 240 | } 241 | 242 | header.setBackgroundColor(Color.GRAY); 243 | 244 | layout.addView(header); 245 | int count = 1; 246 | for (Map.Entry entry : userSignups.entrySet()) { 247 | TableRow signupRow = new TableRow(this); 248 | 249 | TextView username = new TextView(this); 250 | username.setPadding(10, 20, 10, 20); 251 | username.setText(entry.getKey()); 252 | username.setTypeface(null, Typeface.BOLD); 253 | signupRow.addView(username); 254 | List slots = HelperMethods.listifyTimeslotInts(entry.getValue()); 255 | 256 | for (int slot : currentTimeslots) { 257 | TextView avail = new TextView(this); 258 | 259 | if (slots.contains(slot)) { 260 | // User is signed up for this 261 | avail.setText("AVAILABLE"); 262 | avail.setBackgroundColor(GREEN_MAT); 263 | } else if (entry.getValue().isEmpty()) { 264 | avail.setBackgroundColor(Color.RED); 265 | } else { 266 | avail.setBackgroundColor(Color.LTGRAY); 267 | } 268 | avail.setPadding(20, 20, 20, 20); 269 | 270 | signupRow.addView(avail); 271 | } 272 | 273 | final int currentRow = count; 274 | 275 | signupRow.setOnClickListener(new View.OnClickListener() { 276 | int thisRow = currentRow; 277 | 278 | @Override 279 | public void onClick(View view) { 280 | selectedRow = thisRow; 281 | highlightSelection(); 282 | } 283 | }); 284 | 285 | layout.addView(signupRow); 286 | count++; 287 | 288 | } 289 | } 290 | 291 | /** 292 | * This method allows for selection of a table row and displaying a user-friendly list of 293 | * the given user's availability 294 | */ 295 | private void highlightSelection() { 296 | String disp; 297 | TableLayout layout = (TableLayout) findViewById(R.id.tbLayout); 298 | 299 | TableRow highlight = (TableRow)layout.getChildAt(selectedRow); 300 | if (selectedRow != -1) { 301 | 302 | String user = ((TextView)highlight.getChildAt(0)).getText().toString(); 303 | 304 | disp = user + "'s Availability: " + HelperMethods.getTimeString(HelperMethods.listifyTimeslotInts((userSignups.get(user))), format); 305 | } else { 306 | 307 | String users = ""; 308 | int userCount = 0; 309 | 310 | for (Map.Entry entry : userSignups.entrySet()) { 311 | if (HelperMethods.listifyTimeslotInts(entry.getValue()).contains(selectedSlot)) { 312 | userCount++; 313 | users = users + entry.getKey() + ", "; 314 | } 315 | } 316 | 317 | if (userCount > 0) users = users.substring(0, users.length() - 3); 318 | 319 | disp = "For timeslot " + HelperMethods.toTime(selectedSlot, format) + " " + userCount + " user(s) are available: " + users; 320 | } 321 | 322 | ((TextView)findViewById(R.id.tvSelectedUser)).setText(disp); 323 | } 324 | 325 | /** 326 | * This function saves the user's current availability for an event 327 | * @param v View of the button that was pressed 328 | */ 329 | public void saveSelection(View v) { 330 | if (prevSignup) { 331 | // User has signed up previously, so call the update method 332 | if (dbHelper.updateSignup(currentID, currentUser, selectedTimeslots) > 0) { 333 | statusMessage.setText("Successfully saved your availability"); 334 | } else { 335 | statusMessage.setText("Something went wrong"); 336 | } 337 | } else { 338 | // User has not signed up before, so call the insert method 339 | if (dbHelper.addSignup(currentID,currentUser,selectedTimeslots) != -1) { 340 | statusMessage.setText("Successfully saved your availability"); 341 | } else { 342 | statusMessage.setText("Somethign went wrong"); 343 | } 344 | } 345 | statusMessage.show(); 346 | finish(); 347 | } 348 | 349 | /** 350 | * This function updates the display of the user's current selected availability. 351 | */ 352 | private void updateTimeDisplay() { 353 | TextView timeDisplay = (TextView) findViewById(R.id.tvSelectedTimes); 354 | 355 | String disp = "Your Selected Availability: " + HelperMethods.getTimeString(selectedTimeslots, format); 356 | 357 | timeDisplay.setText(disp); 358 | } 359 | 360 | /** 361 | * This function updates the timeframe of the event on creation and when the 12h/24h is toggled. 362 | */ 363 | private void updateTimeframe() { 364 | 365 | TextView eventTimeframe = (TextView) findViewById(R.id.tvEventTimeframe); 366 | 367 | eventTimeframe.setText("Event timeframe: " + HelperMethods.getTimeString(currentTimeslots, format)); 368 | } 369 | 370 | /** 371 | * This function toggles the 12h/24h format 372 | * @param v View of the button that was pressed 373 | */ 374 | public void toggleTimeFormat(View v) { 375 | format = !format; 376 | 377 | if (adminMode) { 378 | displayEventSignups(); 379 | highlightSelection(); 380 | } else { 381 | populateTimeslotTable(); 382 | 383 | updateTimeDisplay(); 384 | } 385 | updateTimeframe(); 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/data/DBContract.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1.data; 2 | 3 | 4 | import android.provider.BaseColumns; 5 | 6 | /** 7 | * DBContract.java 8 | * @author Damian 9 | * @version 1.0 10 | * This class contains the contract work that will help our database class 11 | */ 12 | public final class DBContract { 13 | 14 | // Version should be changed IF any schemas are MODIFIED 15 | public static final int DATABASE_VERSION = 2; 16 | public static final String DATABASE_NAME = "database.db"; 17 | 18 | 19 | /** 20 | * Constructor is private so the contract can never be somehow initialized 21 | */ 22 | private DBContract() {} 23 | 24 | /** 25 | * {Class} Users 26 | * This defines the columns for our Users table 27 | * @since 1.0 28 | */ 29 | public static class UserTable implements BaseColumns { 30 | public static final String TABLE_NAME = "users"; 31 | public static final String COLUMN_NAME_NAME = "name"; 32 | 33 | public static final String CREATE_TABLE = "CREATE TABLE " + 34 | TABLE_NAME + " (" + 35 | _ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + 36 | COLUMN_NAME_NAME + " TEXT COLLATE NOCASE UNIQUE);"; 37 | public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME; 38 | } 39 | 40 | /** 41 | * {Class} Events 42 | * This defines the columns for our Events table. 43 | * @since 1.0 44 | */ 45 | public static class EventTable implements BaseColumns { // If we implement BaseColumns, we can utilize _ID as a default column 46 | public static final String TABLE_NAME = "events"; 47 | public static final String COLUMN_NAME_TITLE = "title"; 48 | public static final String COLUMN_NAME_TIMESLOTS = "timeslots"; 49 | public static final String COLUMN_NAME_CREATOR = "creator"; 50 | public static final String COLUMN_NAME_DAY = "day"; 51 | 52 | public static final String CREATE_TABLE = "CREATE TABLE " + 53 | TABLE_NAME + " (" + 54 | _ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + 55 | COLUMN_NAME_TITLE + " TEXT," + 56 | COLUMN_NAME_DAY + " TEXT," + 57 | COLUMN_NAME_TIMESLOTS + " TEXT," + 58 | COLUMN_NAME_CREATOR + " TEXT);"; 59 | public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME; 60 | } 61 | 62 | /** 63 | * {Class} Signups 64 | * This defines the columns for our Signups table 65 | * @since 1.0 66 | */ 67 | public static class SignupTable implements BaseColumns { 68 | public static final String TABLE_NAME = "signups"; 69 | public static final String COLUMN_NAME_EVENT = "eid"; 70 | public static final String COLUMN_NAME_USER = "user"; 71 | public static final String COLUMN_NAME_AVAIL = "availability"; 72 | 73 | public static final String CREATE_TABLE = "CREATE TABLE " + 74 | TABLE_NAME + " (" + 75 | _ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + 76 | COLUMN_NAME_EVENT + " INTEGER," + 77 | COLUMN_NAME_USER + " TEXT," + 78 | COLUMN_NAME_AVAIL + " TEXT);"; 79 | public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/data/DatabaseHelper.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1.data; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteDatabase; 7 | import android.database.sqlite.SQLiteOpenHelper; 8 | 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * DatabaseHelper.java 16 | * @author Damian, Lane 17 | * @version 1.0 18 | * This class contains helper methods that interact with the Database. This replaced the Dataclass 19 | */ 20 | public class DatabaseHelper extends SQLiteOpenHelper { 21 | /** 22 | * Default constructor for the databasehelper. 23 | * @param context Always the entire application context because we want the database to be for the whole application. 24 | */ 25 | public DatabaseHelper(Context context) { 26 | super(context, DBContract.DATABASE_NAME, null, DBContract.DATABASE_VERSION); 27 | } 28 | 29 | /** 30 | * Called when the DatabaseHelper class is created. Will create database tables if they do not exist. 31 | * @param db Current writable database 32 | */ 33 | @Override 34 | public void onCreate(SQLiteDatabase db) { 35 | // Create all tables 36 | db.execSQL(DBContract.UserTable.CREATE_TABLE); 37 | db.execSQL(DBContract.EventTable.CREATE_TABLE); 38 | db.execSQL(DBContract.SignupTable.CREATE_TABLE); 39 | } 40 | 41 | /** 42 | * Called when the database version is changed in DBContract 43 | * @param db Current writable database 44 | * @param oldVersion Old version of DB. Set in DBContract 45 | * @param newVersion New version of DB. Set in DBContract 46 | */ 47 | @Override 48 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 49 | // Delete all tables 50 | db.execSQL(DBContract.UserTable.DROP_TABLE); 51 | db.execSQL(DBContract.EventTable.DROP_TABLE); 52 | db.execSQL(DBContract.SignupTable.DROP_TABLE); 53 | onCreate(db); 54 | } 55 | 56 | //region User Table Methods 57 | 58 | /** 59 | * 60 | * @param name the name of the new user to add 61 | * @return -1 for failure, otherwise will return the row inserted at. 62 | */ 63 | public long addUser(String name) { 64 | SQLiteDatabase db = this.getWritableDatabase(); // is this okay? 65 | 66 | ContentValues values = new ContentValues(); 67 | values.put(DBContract.UserTable.COLUMN_NAME_NAME, name); 68 | 69 | return db.insert(DBContract.UserTable.TABLE_NAME, null, values); 70 | } 71 | 72 | /** 73 | * This method queries our User table for all Usernames 74 | * @return List of strings containing all users 75 | */ 76 | public List getUsers() { 77 | SQLiteDatabase db = this.getReadableDatabase(); 78 | 79 | // Even though we only get one column, SQLiteDatabase.query() requires a string array 80 | String[] columns = { 81 | DBContract.UserTable.COLUMN_NAME_NAME 82 | }; 83 | String sortOrder = DBContract.UserTable.COLUMN_NAME_NAME + " COLLATE NOCASE ASC"; 84 | 85 | Cursor query = db.query( 86 | DBContract.UserTable.TABLE_NAME, 87 | columns, 88 | null, null, null, null, 89 | sortOrder 90 | ); 91 | 92 | List names = new ArrayList<>(); 93 | while (query.moveToNext()) { 94 | String name = query.getString(query.getColumnIndexOrThrow(DBContract.UserTable.COLUMN_NAME_NAME)); 95 | names.add(name); 96 | } 97 | 98 | query.close(); 99 | 100 | return names; 101 | } 102 | 103 | //endregion 104 | 105 | 106 | 107 | //region Event Table Methods 108 | 109 | /** 110 | * This function will add an event to the event table 111 | * @param e - Event object passed when the save button is clicked with valid event params 112 | * @return event ID 113 | * @since 1.0 114 | */ 115 | public int addEvent(Event e) { 116 | 117 | SQLiteDatabase db = this.getWritableDatabase(); 118 | ContentValues values = new ContentValues(); 119 | 120 | values.put(DBContract.EventTable.COLUMN_NAME_TITLE, e.getName()); 121 | values.put(DBContract.EventTable.COLUMN_NAME_TIMESLOTS, e.getTimeslots()); 122 | values.put(DBContract.EventTable.COLUMN_NAME_CREATOR, e.getCreator()); 123 | values.put(DBContract.EventTable.COLUMN_NAME_DAY, e.getDate()); 124 | 125 | db.insert(DBContract.EventTable.TABLE_NAME, null, values); //Perform insertion 126 | 127 | //Get the ID of the event we just created and return it 128 | String[] columns = {DBContract.EventTable._ID}; 129 | String sortOrder = DBContract.EventTable._ID + " DESC"; 130 | 131 | 132 | Cursor query = db.query( 133 | DBContract.EventTable.TABLE_NAME, 134 | columns, 135 | null, null, null, null, 136 | sortOrder 137 | ); 138 | query.moveToNext(); 139 | int eventID = Integer.parseInt(query.getString(query.getColumnIndexOrThrow(DBContract.EventTable._ID))); 140 | query.close(); 141 | 142 | return eventID; 143 | } 144 | 145 | /** 146 | * This function will get all events from the event table 147 | * @return A sorted ArrayList of Events from the Database 148 | * @since 1.0 149 | */ 150 | public ArrayList getAllEvents() { 151 | 152 | SQLiteDatabase db = this.getReadableDatabase(); 153 | 154 | ArrayList sortedListOfEvents = new ArrayList<>(); // Will be sorted through SQL 155 | 156 | String[] columns = { 157 | DBContract.EventTable._ID, 158 | DBContract.EventTable.COLUMN_NAME_TITLE, 159 | DBContract.EventTable.COLUMN_NAME_TIMESLOTS, 160 | DBContract.EventTable.COLUMN_NAME_CREATOR, 161 | DBContract.EventTable.COLUMN_NAME_DAY 162 | }; 163 | 164 | //Sort by day for now. Could hypothetically get weird when multiple years are involved 165 | String sortOrder = DBContract.EventTable.COLUMN_NAME_DAY + " COLLATE NOCASE ASC"; 166 | 167 | Cursor query = db.query( 168 | DBContract.EventTable.TABLE_NAME, 169 | columns, 170 | null, null, null, null, 171 | sortOrder 172 | ); 173 | 174 | //Populate event vector 175 | while (query.moveToNext()) { 176 | 177 | int id; 178 | String title, timeslots, creator, day; 179 | 180 | id = Integer.parseInt(query.getString(query.getColumnIndexOrThrow(DBContract.EventTable._ID))); 181 | title = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_TITLE)); 182 | timeslots = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_TIMESLOTS)); 183 | creator = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_CREATOR)); 184 | day = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_DAY)); 185 | 186 | //Create Event object from row and add to Vector 187 | Event e = new Event(id, day, title, creator, timeslots); // LOL This stuff was in the wrong order... Come on guys... 188 | sortedListOfEvents.add(e); 189 | } 190 | 191 | query.close(); 192 | 193 | return sortedListOfEvents; 194 | } 195 | 196 | /** 197 | * Get events from given user. 198 | * @param user - Username to retrieve events for. 199 | * @return Sorted Event vector of a given user's created events 200 | */ 201 | public ArrayList getUserEvents(String user) { 202 | SQLiteDatabase db = this.getReadableDatabase(); 203 | 204 | ArrayList sortedListOfEvents = new ArrayList<>(); // Will be sorted through SQL 205 | 206 | String[] userArr = {user}; //(Needs to be in an array to use as a WHERE argument) 207 | 208 | String[] columns = { 209 | DBContract.EventTable._ID, 210 | DBContract.EventTable.COLUMN_NAME_TITLE, 211 | DBContract.EventTable.COLUMN_NAME_TIMESLOTS, 212 | DBContract.EventTable.COLUMN_NAME_CREATOR, 213 | DBContract.EventTable.COLUMN_NAME_DAY 214 | }; 215 | 216 | //Sort by day for now. Could hypothetically get weird when multiple years are involved 217 | String sortOrder = DBContract.EventTable.COLUMN_NAME_DAY + " COLLATE NOCASE ASC"; 218 | 219 | Cursor query = db.query( 220 | DBContract.EventTable.TABLE_NAME, 221 | columns, 222 | "creator = ?", userArr, null, null, 223 | sortOrder 224 | ); 225 | 226 | //Populate event List 227 | while (query.moveToNext()) { 228 | 229 | int id; 230 | String title, timeslots, creator, day; 231 | 232 | id = Integer.parseInt(query.getString(query.getColumnIndexOrThrow(DBContract.EventTable._ID))); 233 | title = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_TITLE)); 234 | timeslots = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_TIMESLOTS)); 235 | creator = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_CREATOR)); 236 | day = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_DAY)); 237 | 238 | //Create Event object from row and add to Vector 239 | Event e = new Event(id, day, title, creator, timeslots); 240 | sortedListOfEvents.add(e); 241 | } 242 | 243 | query.close(); 244 | 245 | return sortedListOfEvents; 246 | } 247 | 248 | //endregion 249 | 250 | 251 | 252 | //region Signup Table Methods 253 | 254 | /** 255 | * @param eventID ID of event in Table 256 | * @return Event object containing all event info 257 | */ 258 | public Event getEvent(int eventID) { 259 | 260 | SQLiteDatabase db = this.getReadableDatabase(); 261 | 262 | String[] columns = { 263 | DBContract.EventTable.COLUMN_NAME_TIMESLOTS, 264 | DBContract.EventTable.COLUMN_NAME_CREATOR, 265 | DBContract.EventTable.COLUMN_NAME_DAY, 266 | DBContract.EventTable.COLUMN_NAME_TITLE 267 | }; 268 | 269 | String[] where = {Integer.toString(eventID)}; 270 | 271 | Cursor query = db.query( 272 | DBContract.EventTable.TABLE_NAME, 273 | columns, 274 | "_ID = ?", where , null, null, 275 | null 276 | ); 277 | 278 | query.moveToNext(); 279 | 280 | String date = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_DAY)); 281 | String creator = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_CREATOR)); 282 | String name = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_TITLE)); 283 | String timeslots = query.getString(query.getColumnIndexOrThrow(DBContract.EventTable.COLUMN_NAME_TIMESLOTS)); 284 | 285 | Event returnEvent = new Event(eventID, date, name, creator, timeslots); 286 | 287 | 288 | query.close(); 289 | 290 | return returnEvent; 291 | } 292 | 293 | /** 294 | * This method will add a users availability to the signup table 295 | * @param eventID int ID of event 296 | * @param user String username that is signing up 297 | * @param availability Integer List of timeslots 298 | * @return long value of the row in the table that was created 299 | */ 300 | public long addSignup(int eventID, String user, List availability) {// TODO create entry in signups table 301 | SQLiteDatabase db = this.getWritableDatabase(); 302 | 303 | String avail = HelperMethods.stringifyTimeslotInts(availability); 304 | 305 | ContentValues values = new ContentValues(); 306 | values.put(DBContract.SignupTable.COLUMN_NAME_USER, user); 307 | values.put(DBContract.SignupTable.COLUMN_NAME_AVAIL, avail); 308 | values.put(DBContract.SignupTable.COLUMN_NAME_EVENT, eventID); 309 | 310 | return db.insert(DBContract.SignupTable.TABLE_NAME, null, values); 311 | } 312 | 313 | /** 314 | * This method will return a Hashmap of users along with availability for a given event 315 | * @param eventID int ID of event 316 | * @return Hashmap of user keypairs with availability keyvalues 317 | */ 318 | public Map getSignups(int eventID) { // TODO return list of signed up users(?) for given event 319 | SQLiteDatabase db = this.getReadableDatabase(); 320 | Map userSignup = new HashMap<>(); 321 | 322 | String[] columns = { 323 | DBContract.SignupTable.COLUMN_NAME_USER, 324 | DBContract.SignupTable.COLUMN_NAME_AVAIL 325 | }; 326 | String[] where = {Integer.toString(eventID)}; 327 | 328 | Cursor query = db.query( 329 | DBContract.SignupTable.TABLE_NAME, 330 | columns, 331 | "eid = ?", where, null, null, 332 | null 333 | ); 334 | 335 | while (query.moveToNext()) { 336 | userSignup.put(query.getString(query.getColumnIndexOrThrow(DBContract.SignupTable.COLUMN_NAME_USER)), 337 | query.getString(query.getColumnIndexOrThrow(DBContract.SignupTable.COLUMN_NAME_AVAIL))); 338 | } 339 | 340 | return userSignup; 341 | } 342 | 343 | /** 344 | * This method will update a given user's availability for an event. 345 | * @param eventID int ID of event 346 | * @param user String username that is changing availability 347 | * @param availability Integer List of timeslots 348 | * @return int value of the row in the table that was updated 349 | */ 350 | public int updateSignup(int eventID, String user, List availability) { 351 | SQLiteDatabase db = this.getWritableDatabase(); 352 | 353 | String avail = HelperMethods.stringifyTimeslotInts(availability); 354 | 355 | ContentValues values = new ContentValues(); 356 | values.put(DBContract.SignupTable.COLUMN_NAME_AVAIL, avail); 357 | 358 | String selection = DBContract.SignupTable.COLUMN_NAME_USER + " = ? AND " + DBContract.SignupTable.COLUMN_NAME_EVENT + " = ?"; 359 | String[] selectionArgs = {user, Integer.toString(eventID)}; 360 | 361 | return db.update( 362 | DBContract.SignupTable.TABLE_NAME, 363 | values, 364 | selection, 365 | selectionArgs 366 | ); 367 | } 368 | 369 | 370 | 371 | //endregion 372 | } 373 | -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/data/Event.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1.data; 2 | 3 | 4 | /** 5 | * Event.java 6 | * @author Damian, Lane 7 | * @version 1.0 8 | * 9 | * Event DataType for keeping track of events 10 | */ 11 | public class Event implements Comparable { 12 | 13 | private int id; 14 | private String date; 15 | private String name; 16 | private String creator; 17 | private String timeslots; 18 | 19 | /** 20 | * Constructor for an Event. Events will always be constructed this way. 21 | * @param inputID int ID of the event 22 | * @param inputDate String date of format MM/DD/YYYY 23 | * @param inputName String name of the Event Title 24 | * @param inputCreator String name of the Event Creator 25 | * @param inputTimeslots String timeslot list of scheduled timeslots 26 | */ 27 | public Event(int inputID, String inputDate, String inputName, String inputCreator, String inputTimeslots) { 28 | id = inputID; 29 | name = inputName; 30 | date = inputDate; 31 | creator = inputCreator; 32 | timeslots = inputTimeslots; 33 | } 34 | 35 | /** 36 | * Allows events to be compared to each other. 37 | * @param otherEvent Event object of event to compare to 38 | * @return int < 0 if given event is later than current event. int = 0 if given event is same day as current. int > 0 otherwise 39 | */ 40 | public int compareTo(Event otherEvent) { 41 | int[] currentDate = HelperMethods.getMonthDayYear(date); 42 | int[] otherDate = HelperMethods.getMonthDayYear(otherEvent.getDate()); 43 | 44 | if (currentDate[2] == otherDate[2]) { 45 | if (currentDate[0] == otherDate[0]) { 46 | return currentDate[1] - otherDate[1]; 47 | } else { 48 | return currentDate[0] - otherDate[0]; 49 | } 50 | } else { 51 | return currentDate[2] - otherDate[2]; 52 | } 53 | } 54 | 55 | // We will probably not need setters. 56 | 57 | // Getters 58 | 59 | /** 60 | * Getter for the Event ID 61 | * @return int ID 62 | */ 63 | public int getID() { return id; } 64 | 65 | /** 66 | * Getter for the Date String 67 | * @return String date of format MM/DD/YYYY 68 | */ 69 | public String getDate() { 70 | return date; 71 | } 72 | 73 | /** 74 | * Getter for the Event Name String 75 | * @return String event name 76 | */ 77 | public String getName() { 78 | return name; 79 | } 80 | 81 | /** 82 | * Getter for the Event Creator String 83 | * @return String event creator 84 | */ 85 | public String getCreator() { 86 | return creator; 87 | } 88 | 89 | /** 90 | * Getter for the Event Schedule String 91 | * @return String of all timeslots for event 92 | */ 93 | public String getTimeslots() { 94 | return timeslots; 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /benign/app/src/main/java/wubbalubbadubdub/benignhw1/data/HelperMethods.java: -------------------------------------------------------------------------------- 1 | package wubbalubbadubdub.benignhw1.data; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Calendar; 6 | import java.util.Collections; 7 | import java.util.List; 8 | 9 | /** 10 | * HelperMethods.java 11 | * @author Lane, Damian 12 | * @version 1.0 13 | * Contains methods used to assist functionality of activities 14 | */ 15 | public class HelperMethods { 16 | 17 | /** 18 | * Private constructor so that this class is never initialized 19 | */ 20 | private HelperMethods(){} 21 | 22 | /** 23 | * @param timeslot - int from 0-47, represents the 48 30min timeslots from 00:00-23:30 24 | * @param format - True: 24h format | False: 12h format 25 | * @return - A time formatted in either 12h or 24h format. 26 | * @since 1.0 27 | */ 28 | public static String toTime(int timeslot, boolean format) { 29 | 30 | int hour; 31 | String min; 32 | 33 | //Convert 0-47 integer format to 12h or 24h format 34 | if (format) hour = timeslot / 2; 35 | else hour = (timeslot >= 26) ? ((timeslot - 24) / 2) : (timeslot / 2); 36 | min = ((timeslot % 2) == 0) ? "00" : "30"; 37 | if (!format && (hour == 0)) hour = 12; //Special case: 0(int)->12:00(12h) 38 | 39 | String time = hour + ":" + min; //Build time string 40 | time = (format && (hour < 10)) ? ("0" + time) : time; //Add leading zero if needed in 24h format 41 | if (!format) time = (timeslot < 24) ? time + "am" : time + "pm"; // AM/PM for 12h format 42 | 43 | return time; 44 | } 45 | 46 | /** 47 | * @param month - month of a given date 48 | * @param day - day of a given date 49 | * @param year - year of a given date 50 | * @return a string in MM/DD/YYYY format 51 | * @since 1.0 52 | */ 53 | public static String dateToString(int month, int day, int year) 54 | {return (month + "/" + day + "/" + year);} 55 | 56 | /** 57 | * @param date - A date in the string form as created by dateToString() 58 | * @return [0]: month | [1]: day | [2]: year (all ints) 59 | */ 60 | /* public static int[] dateSplitString(String date) { 61 | int[] splitDate = {Integer.parseInt(date.substring(0,2)), 62 | Integer.parseInt(date.substring(3,5)), 63 | Integer.parseInt(date.substring(6))}; 64 | return splitDate; 65 | }*/ 66 | 67 | /** 68 | * @return a string in MM/DD/YYYY format of the current year 69 | * @since 1.0 70 | */ 71 | public static int[] getCurrentDate() { 72 | Calendar cal = Calendar.getInstance(); 73 | int month = cal.get(Calendar.MONTH); 74 | int day = cal.get(Calendar.DAY_OF_MONTH); 75 | int year = cal.get(Calendar.YEAR); 76 | int[] date = {month, day, year}; 77 | return date; 78 | } 79 | 80 | /** 81 | * Converts List of timeslots to a readable integer string 82 | * @param timeslots - list of timeslots in integer form 83 | * @param format - 12h/24h format boolean 84 | * @return concatenated string of timeslot list 85 | */ 86 | public static String getTimeString(List timeslots, boolean format) { 87 | // Sort it 88 | Collections.sort(timeslots); 89 | 90 | String timestring = ""; 91 | 92 | int prevTime = -1; 93 | int workingTimeslot = -1; 94 | for(Integer slot : timeslots) { 95 | if (workingTimeslot == -1) {// First iteration 96 | workingTimeslot = slot; 97 | } else if (slot != prevTime + 1) { 98 | // Make time with workingtimeslot and prevTime 99 | timestring = timestring + toTime(workingTimeslot, format) + "-" + toTime(prevTime + 1, format) + ", "; 100 | workingTimeslot = slot; 101 | } 102 | prevTime = slot; 103 | } 104 | if (workingTimeslot != -1) { 105 | // At the end finish out the working slot. 106 | timestring = timestring + toTime(workingTimeslot, format) + "-" + toTime((prevTime + 1) % 48, format); 107 | } 108 | if (workingTimeslot == 0 && prevTime == 47) timestring = "ALL DAY LONG"; 109 | 110 | if (timestring.isEmpty()) timestring = "NOT AVAILABLE AT ALL"; 111 | 112 | return timestring; 113 | } 114 | 115 | 116 | /** 117 | * Counterpart to listifyTimeslotInts (list->String) 118 | * @param timeslotInts - List of timeslots in integer form 119 | * @return comma separated list of timeslots as a String for storage in db 120 | */ 121 | public static String stringifyTimeslotInts(List timeslotInts) { 122 | //Build string -- will look like "0,1,2,4,5" for example 123 | String stringList = ""; 124 | for (Integer slot : timeslotInts) 125 | stringList += (timeslotInts.indexOf(slot) != (timeslotInts.size() - 1)) ? (slot + ",") : slot; 126 | return stringList; 127 | } 128 | 129 | /** 130 | * Counterpart to stringifyTimeslotInts (String->list) 131 | * @param timeslotString - comma separated String list formatted for storage in db 132 | * @return List of timeslots in integer form 133 | */ 134 | public static List listifyTimeslotInts(String timeslotString) { 135 | List timeslotStrs = new ArrayList<>(); 136 | List timeslotInts = new ArrayList<>(); 137 | 138 | timeslotStrs = Arrays.asList(timeslotString.split("\\s*,\\s*")); //Regex to interpret CSVs 139 | if (!timeslotString.isEmpty()) { 140 | for (String slot : timeslotStrs) timeslotInts.add(Integer.parseInt(slot)); 141 | } 142 | 143 | return timeslotInts; 144 | } 145 | 146 | /** 147 | * Conversion of event strings to integer values 148 | * @param eventDateString String date of format MM/DD/YYYY 149 | * @return Int array with index 0 = month, 1 = day, 2 = year 150 | */ 151 | public static int[] getMonthDayYear(String eventDateString) { 152 | String[] mmddyyyy = eventDateString.split("/"); 153 | 154 | int[] returnArray = {Integer.parseInt(mmddyyyy[0]), Integer.parseInt(mmddyyyy[1]), Integer.parseInt(mmddyyyy[2])}; 155 | 156 | return returnArray; 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /benign/app/src/main/res/layout/activity_add_event.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 34 | 35 | 44 | 45 | 56 | 57 | 74 | 75 | 88 | 89 |