Compare commits
2 Commits
50df5e961d
...
bdc1a6f44a
Author | SHA1 | Date | |
---|---|---|---|
bdc1a6f44a | |||
09c66095ed |
69
Summer-2024/CS-3424/Midterm-Notes.org
Normal file
@ -0,0 +1,69 @@
|
||||
* Systems Programming Midterm Topics
|
||||
1. Linux environment / shell commands
|
||||
- Common commands
|
||||
- Chmod/permissions
|
||||
- Wildcards
|
||||
- Input/output redirection
|
||||
- Shell parsing steps
|
||||
- Shell command resolution variables
|
||||
- Shell vs environment and their inheritance
|
||||
- Exit statuses
|
||||
- Subshells / child shells
|
||||
- Arithmetic (operators: expansion vs evaluation)
|
||||
- Floating arithmetic in bash: how?
|
||||
2. Bash Scripting
|
||||
3. ~find~/~grep~
|
||||
4. Regular expressions (BRE vs ERE)
|
||||
5. ~sed~
|
||||
|
||||
NOTE: No AWK material will be covered on the exam
|
||||
|
||||
* Example Questions
|
||||
1. Answer =True= or =False= for the following statements:
|
||||
- [TRUE] The extended regular expression ~{0,1}~ is equivalent to the ~?~ quantifier?
|
||||
- [FALSE] An exit status of ~0~ is used to indicate success.
|
||||
- [FALSE] Given the string "abc123" the regex ~/[a-z]{1,3}/~ will produce a match of "a".
|
||||
- [FALSE] The following loop will never execute:
|
||||
#+begin_src bash
|
||||
while [ 0 ]; do let i++; echo $i; done
|
||||
#+end_src
|
||||
- [TRUE] The following loop will never execute:
|
||||
#+begin_src bash
|
||||
while (( 0 )); do let i++; echo $i; done
|
||||
#+end_src
|
||||
- [TRUE] ~sed~ will emit the contents of the pattern space, including a trailing newline character, by default at the end of each input cycle.
|
||||
- [FALSE] The following bash filename pattern will match all text files in the user's current directory:
|
||||
#+begin_src bash
|
||||
ls -la .*\.txt
|
||||
#+end_src
|
||||
- [TRUE] The ~source~ built-in executes the contents of a specified file within the current script (i.e. no subshell is utilized).
|
||||
- [FALSE] ~grep~ uses extended regular expressions by default
|
||||
2. Enter the octal number corresponding to the following Linux file permissions: ~rwxr-x---~
|
||||
Answer: ~0750~
|
||||
3. Write out the erroneous line numbers from the following script (hint there are six):
|
||||
#+begin_src bash
|
||||
data="./data"
|
||||
org_data=/usr/local/courses/ssilvestro/cs3424/Spring21/assign1/
|
||||
|
||||
if [[ $# -eq 1 ]]; then
|
||||
data = $1
|
||||
else if [[ $# -eq 2 ]]; then
|
||||
data = $1
|
||||
orig_data = $2
|
||||
fi
|
||||
|
||||
if [[! -d $data]]; then
|
||||
echo "ERROR: data directory '$data' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
if [[ not -d $orig_data ]]; then
|
||||
echo "ERROR: original data directory '$data' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
echo "rm -rf \"$data\"..."
|
||||
rm -rf "$data"
|
||||
|
||||
echo "cp -r \"$org_data\" \"$data\"..."
|
||||
cp -r "$orig_data" "$data"
|
||||
#+end_src
|
||||
Answer: ~4,5,6,7,9,13~
|
BIN
Summer-2024/CS-3424/Quizzes/Quiz-6/Assignment.pdf
Normal file
11
Summer-2024/CS-3443/LakeWatch/.envrc
Normal file
@ -0,0 +1,11 @@
|
||||
export APP_API_HOST="localhost"
|
||||
export APP_API_PORT="8000"
|
||||
|
||||
export APP_DATABASE_HOST="localhost"
|
||||
export APP_DATABASE_PORT="5432"
|
||||
export APP_DATABASE_USERNAME="postgres"
|
||||
export APP_DATABASE_PASSWORD="password"
|
||||
export APP_DATABASE_NAME="lakewatch"
|
||||
export APP_DATABASE_REQUIRE_SSL="false"
|
||||
|
||||
export DATABASE_URL="postgres://${APP_DATABASE_USERNAME}:${APP_DATABASE_PASSWORD}@${APP_DATABASE_HOST}:${APP_DATABASE_PORT}/${APP_DATABASE_NAME}"
|
1
Summer-2024/CS-3443/LakeWatch/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.idea/
|
10
Summer-2024/CS-3443/LakeWatch/LakeWatch/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
3
Summer-2024/CS-3443/LakeWatch/LakeWatch/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# `LakeWatch`
|
||||
|
||||
This repository contains the actual Android application.
|
1
Summer-2024/CS-3443/LakeWatch/LakeWatch/app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
43
Summer-2024/CS-3443/LakeWatch/LakeWatch/app/build.gradle.kts
Normal file
@ -0,0 +1,43 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "edu.utsa.cs3443.lakewatch"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "edu.utsa.cs3443.lakewatch"
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.activity)
|
||||
implementation(libs.constraintlayout)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
}
|
21
Summer-2024/CS-3443/LakeWatch/LakeWatch/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@ -0,0 +1,26 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("edu.utsa.cs3443.lakewatch", appContext.getPackageName());
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".model.userSettings"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.LakeWatch"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainRampMenuActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".BoatRampActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".WaterLevelActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".WeatherActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,111 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import edu.utsa.cs3443.lakewatch.model.BoatRampData;
|
||||
import edu.utsa.cs3443.lakewatch.model.BoatRampStatus;
|
||||
|
||||
public class BoatRampActivity extends AppCompatActivity {
|
||||
|
||||
/**
|
||||
* Drive the view for a single boat ramp page
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_boat_ramp);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
BoatRampData rampData = (BoatRampData) this.getIntent().getExtras().getSerializable("rampData");
|
||||
((TextView)this.findViewById(R.id.rampName)).setText(rampData.getName());
|
||||
|
||||
ImageView rampImage = this.findViewById(R.id.rampImage);
|
||||
for (Field field : R.drawable.class.getFields()) {
|
||||
String fieldName = field.getName();
|
||||
if (fieldName.equals("ramp" + rampData.getRampNumber())) {
|
||||
rampImage.setImageResource(this.getResources().getIdentifier(field.getName(), "drawable", this.getPackageName()));
|
||||
}
|
||||
}
|
||||
|
||||
ImageView statusIcon = this.findViewById(R.id.statusIcon);
|
||||
GradientDrawable statusShape = new GradientDrawable();
|
||||
statusShape.setStroke(3, Color.parseColor("#000000"));
|
||||
statusShape.setCornerRadius(8000);
|
||||
if (rampData.getStatus() == BoatRampStatus.OPEN) {
|
||||
statusIcon.setImageResource(R.drawable.circle_check);
|
||||
statusShape.setColor(ContextCompat.getColor(this, R.color.rampStatusOpen));
|
||||
} else if (rampData.getStatus() == BoatRampStatus.CLOSED) {
|
||||
statusIcon.setImageResource(R.drawable.circle_x);
|
||||
statusShape.setColor(ContextCompat.getColor(this, R.color.rampStatusClosed));
|
||||
} else {
|
||||
statusIcon.setImageResource(R.drawable.circle_guess);
|
||||
statusShape.setColor(ContextCompat.getColor(this, R.color.rampStatusUnknown));
|
||||
}
|
||||
CardView statusCard = this.findViewById(R.id.statusCard);
|
||||
statusCard.setBackground(statusShape);
|
||||
((TextView)this.findViewById(R.id.statusText)).setText(rampData.getStatus().toString());
|
||||
|
||||
GradientDrawable cardShape = new GradientDrawable();
|
||||
cardShape.setColor(ContextCompat.getColor(this, R.color.rampInfoBackground));
|
||||
cardShape.setStroke(3, Color.parseColor("#000000"));
|
||||
cardShape.setCornerRadius(8000);
|
||||
|
||||
CardView openTimesCard = this.findViewById(R.id.openTimes);
|
||||
((TextView)openTimesCard.findViewById(R.id.openTimesText)).setText(rampData.getOpenTimes());
|
||||
openTimesCard.setBackground(cardShape);
|
||||
|
||||
CardView addressCard = this.findViewById(R.id.address);
|
||||
((TextView)addressCard.findViewById(R.id.addressText)).setText(rampData.getAddress());
|
||||
addressCard.setBackground(cardShape);
|
||||
addressCard.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("", rampData.getAddress());
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toast toast = Toast.makeText(view.getContext(), "Address copied to clipboard!", Toast.LENGTH_SHORT);
|
||||
View toastView = toast.getView();
|
||||
toastView.findViewById(android.R.id.message).setBackgroundColor(Color.TRANSPARENT);
|
||||
toastView.getBackground().setTint(ContextCompat.getColor(toastView.getContext(), R.color.buttonBackgroundColor));
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
|
||||
CardView operatorCard = this.findViewById(R.id.operator);
|
||||
((TextView)operatorCard.findViewById(R.id.operatorText)).setText(rampData.getOperator());
|
||||
operatorCard.setBackground(cardShape);
|
||||
|
||||
CardView lastUpdatedCard = this.findViewById(R.id.lastUpdated);
|
||||
((TextView)lastUpdatedCard.findViewById(R.id.lastUpdatedText)).setText(DateTimeFormatter.ofPattern("MM/dd/yyyy").format(rampData.getLastUpdated()));
|
||||
lastUpdatedCard.setBackground(cardShape);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
//Button Initialization(s)
|
||||
Button weatherButton = findViewById(R.id.button); //Weather
|
||||
Button waterStatusButton = findViewById(R.id.button2); //WaterStatus
|
||||
Button rampsButton = findViewById(R.id.button3); //Ramps
|
||||
Button settingsButton = findViewById(R.id.settingsButton); // Settings
|
||||
|
||||
//Weather View OnClickListener
|
||||
weatherButton.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View v) { openWeatherActivity(); }
|
||||
});
|
||||
|
||||
//Water Status View OnClickListener
|
||||
waterStatusButton.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View v) { openWaterLevelActivity();}
|
||||
});
|
||||
|
||||
//Boat Ramps View OnClickListener
|
||||
rampsButton.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
openMainRampMenuActivity();
|
||||
}
|
||||
});
|
||||
|
||||
//Settings View OnClickListener
|
||||
settingsButton.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
openSettingsActivity();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//This function is used to navigate to the settings menu via the intent object
|
||||
private void openSettingsActivity()
|
||||
{
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void openWeatherActivity()
|
||||
{
|
||||
Intent intent = new Intent(this, WeatherActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void openWaterLevelActivity()
|
||||
{
|
||||
Intent intent = new Intent(this, WaterLevelActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void openMainRampMenuActivity()
|
||||
{
|
||||
Intent intent = new Intent(this, MainRampMenuActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import edu.utsa.cs3443.lakewatch.model.BoatRampData;
|
||||
import edu.utsa.cs3443.lakewatch.model.BoatRampStatus;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class MainRampMenuActivity extends AppCompatActivity {
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
/**
|
||||
* The main driver behind the full listing of the boat ramps
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main_ramp_menu);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
findViewById(R.id.main),
|
||||
(v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
Callable<ArrayList<BoatRampData>> fetchRampDataTask =
|
||||
() -> {
|
||||
ArrayList<BoatRampData> fetchedData = BoatRampData.fetchData();
|
||||
BoatRampData.saveData(this.findViewById(R.id.main).getContext(), fetchedData);
|
||||
return fetchedData;
|
||||
};
|
||||
|
||||
Future<ArrayList<BoatRampData>> future = executorService.submit(fetchRampDataTask);
|
||||
new Handler(Looper.getMainLooper())
|
||||
.post(
|
||||
() -> {
|
||||
ArrayList<BoatRampData> allRampData = new ArrayList<>();
|
||||
try {
|
||||
allRampData = future.get();
|
||||
} catch (Exception e) {
|
||||
Toast toast =
|
||||
Toast.makeText(
|
||||
this.findViewById(R.id.main).getContext(),
|
||||
"API Fetch Failed, failling back to cache.",
|
||||
Toast.LENGTH_SHORT);
|
||||
View toastView = toast.getView();
|
||||
toastView.findViewById(android.R.id.message).setBackgroundColor(Color.TRANSPARENT);
|
||||
toastView
|
||||
.getBackground()
|
||||
.setTint(
|
||||
ContextCompat.getColor(
|
||||
toastView.getContext(), R.color.buttonBackgroundColor));
|
||||
toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 50);
|
||||
toast.show();
|
||||
|
||||
Toast cacheToast =
|
||||
Toast.makeText(
|
||||
this.findViewById(R.id.main).getContext(),
|
||||
"Failed to load boat ramp data!",
|
||||
Toast.LENGTH_SHORT);
|
||||
View cacheToastView = cacheToast.getView();
|
||||
cacheToastView
|
||||
.findViewById(android.R.id.message)
|
||||
.setBackgroundColor(Color.TRANSPARENT);
|
||||
cacheToastView
|
||||
.getBackground()
|
||||
.setTint(
|
||||
ContextCompat.getColor(
|
||||
cacheToastView.getContext(), R.color.buttonBackgroundColor));
|
||||
cacheToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 50);
|
||||
|
||||
try {
|
||||
allRampData =
|
||||
BoatRampData.loadCachedData(this.findViewById(R.id.main).getContext());
|
||||
} catch (Exception ex) {
|
||||
cacheToast.show();
|
||||
}
|
||||
}
|
||||
|
||||
LinearLayout rampListing = this.findViewById(R.id.rampListing);
|
||||
int ramps_open = 0;
|
||||
LayoutInflater inflater =
|
||||
(LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
for (BoatRampData rampData : allRampData) {
|
||||
if (rampData.getStatus() == BoatRampStatus.OPEN) {
|
||||
ramps_open++;
|
||||
}
|
||||
|
||||
View rampView = inflater.inflate(R.layout.ramp_menu_card, rampListing, false);
|
||||
CardView rampMenuCard = rampView.findViewById(R.id.rampMenuCard);
|
||||
((TextView) rampMenuCard.findViewById(R.id.rampName)).setText(rampData.getName());
|
||||
((TextView) rampMenuCard.findViewById(R.id.rampStatus))
|
||||
.setText(rampData.getStatus().toString());
|
||||
ImageView statusImage = rampView.findViewById(R.id.statusIcon);
|
||||
GradientDrawable shape = new GradientDrawable();
|
||||
|
||||
if (rampData.getStatus() == BoatRampStatus.OPEN) {
|
||||
statusImage.setImageResource(R.drawable.circle_check);
|
||||
shape.setColor(ContextCompat.getColor(this, R.color.rampStatusOpen));
|
||||
} else if (rampData.getStatus() == BoatRampStatus.CLOSED) {
|
||||
statusImage.setImageResource(R.drawable.circle_x);
|
||||
shape.setColor(ContextCompat.getColor(this, R.color.rampStatusClosed));
|
||||
} else {
|
||||
statusImage.setImageResource(R.drawable.circle_guess);
|
||||
shape.setColor(ContextCompat.getColor(this, R.color.rampStatusUnknown));
|
||||
}
|
||||
|
||||
shape.setStroke(3, Color.parseColor("#000000"));
|
||||
shape.setCornerRadius(80);
|
||||
rampMenuCard.setBackground(shape);
|
||||
|
||||
rampMenuCard.setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
launchBoatRampActivity(rampData);
|
||||
}
|
||||
});
|
||||
rampListing.addView(rampView);
|
||||
}
|
||||
((TextView) this.findViewById(R.id.rampsOpen))
|
||||
.setText(String.format("%d/%d Ramps Open", ramps_open, allRampData.size()));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch a specific page of a boat ramp
|
||||
*
|
||||
* @param rampData The ramp data to use for the page
|
||||
*/
|
||||
private void launchBoatRampActivity(BoatRampData rampData) {
|
||||
Intent intent = new Intent(this, BoatRampActivity.class);
|
||||
intent.putExtra("rampData", (Serializable) rampData);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import edu.utsa.cs3443.lakewatch.model.BoatRampData;
|
||||
import edu.utsa.cs3443.lakewatch.model.WaterLevelData;
|
||||
import edu.utsa.cs3443.lakewatch.model.WeatherData;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_settings);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
//Button Initializations
|
||||
Button btnToggleDark = findViewById(R.id.button5);
|
||||
Button dataFetchButton = findViewById(R.id.button6);
|
||||
Button clearCacheButton = findViewById(R.id.button7);
|
||||
|
||||
//Saving state of our app
|
||||
//using SharedPreferences
|
||||
//necessary for Dark Mode
|
||||
SharedPreferences sharedPreferences = getSharedPreferences("sharedPrefs",MODE_PRIVATE);
|
||||
final SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
final boolean isDarkModeOn = sharedPreferences.getBoolean("isDarkModeOn",false);
|
||||
|
||||
// When user reopens the app
|
||||
// after applying a respective
|
||||
// color mode
|
||||
if(isDarkModeOn)
|
||||
{
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
btnToggleDark.setText("DARK MODE ON");
|
||||
}
|
||||
else {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
btnToggleDark.setText("DARK MODE OFF");
|
||||
}
|
||||
|
||||
//Dark Mode OnClickListener
|
||||
//contains the logic to toggle
|
||||
//Dark mode
|
||||
btnToggleDark.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
// When user taps the enable/disable
|
||||
// dark mode button
|
||||
if (isDarkModeOn) {
|
||||
// if dark mode is on
|
||||
// it will turn off dark mode
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
// sets isDarkModeOn
|
||||
// boolean to false
|
||||
editor.putBoolean("isDarkModeOn", false);
|
||||
editor.apply();
|
||||
}
|
||||
else {
|
||||
// if dark mode is off
|
||||
// it will turn on dark mode
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
// sets isDarkModeOn
|
||||
// boolean to true
|
||||
editor.putBoolean("isDarkModeOn", true);
|
||||
editor.apply();
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dataFetchButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Toast toast = Toast.makeText(view.getContext(), "Data Fetched.", Toast.LENGTH_SHORT);
|
||||
View toastView = toast.getView();
|
||||
toastView.findViewById(android.R.id.message).setBackgroundColor(Color.TRANSPARENT);
|
||||
toastView.getBackground().setTint(ContextCompat.getColor(toastView.getContext(), R.color.buttonBackgroundColor));
|
||||
toast.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM,0,50);
|
||||
|
||||
|
||||
executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
Callable<ArrayList<BoatRampData>> fetchRampDataTask =
|
||||
() -> {
|
||||
ArrayList<BoatRampData> fetchedData = BoatRampData.fetchData();
|
||||
BoatRampData.saveData(view.getContext(), fetchedData);
|
||||
return fetchedData;
|
||||
};
|
||||
|
||||
Future<ArrayList<BoatRampData>> future = executorService.submit(fetchRampDataTask);
|
||||
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
try {
|
||||
BoatRampData.saveData(view.getContext(), future.get());
|
||||
} catch (Exception e) {
|
||||
toast.setText("Failed to force a data fetch!");
|
||||
}
|
||||
});
|
||||
// Fetch Water Level Data
|
||||
toast.show();
|
||||
|
||||
WaterLevelData.forceDataFetch(getApplicationContext());
|
||||
}
|
||||
});
|
||||
|
||||
clearCacheButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Toast toast = Toast.makeText(view.getContext(), "Cache Cleared.", Toast.LENGTH_SHORT);
|
||||
View toastView = toast.getView();
|
||||
toastView.findViewById(android.R.id.message).setBackgroundColor(Color.TRANSPARENT);
|
||||
toastView.getBackground().setTint(ContextCompat.getColor(toastView.getContext(), R.color.buttonBackgroundColor));
|
||||
toast.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM,0,50);
|
||||
try {
|
||||
BoatRampData.wipeCache(view.getContext());
|
||||
} catch (IOException e) {
|
||||
toast.setText("Failed to wipe ramp data cache!");
|
||||
}
|
||||
|
||||
toast.show();
|
||||
|
||||
try {
|
||||
WeatherData.wipeCache(view.getContext());
|
||||
} catch (IOException e) {
|
||||
toast.setText("Failed to wipe weather data cache!");
|
||||
}
|
||||
toast.show();
|
||||
|
||||
WaterLevelData.clearCache(getApplicationContext());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,117 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import edu.utsa.cs3443.lakewatch.model.WaterLevelData;
|
||||
|
||||
public class WaterLevelActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_water);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
new FetchWaterLevelDataTask().execute();
|
||||
}
|
||||
private class FetchWaterLevelDataTask extends AsyncTask<Void, Void, WaterLevelData> {
|
||||
|
||||
@Override
|
||||
protected WaterLevelData doInBackground(Void... voids) {
|
||||
WaterLevelData data = null;
|
||||
try {
|
||||
String jsonResponse = WaterLevelData.getJsonResponseFromApi();
|
||||
data = WaterLevelData._loadWaterLevelData(jsonResponse);
|
||||
if (data != null) {
|
||||
data.saveWaterLevelData(WaterLevelActivity.this);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
data = WaterLevelData.loadSavedWaterLevelData(WaterLevelActivity.this);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(WaterLevelData currentData) {
|
||||
updateUI(currentData);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUI(WaterLevelData currentData) {
|
||||
TableLayout tableLayout = findViewById(R.id.tableLayout);
|
||||
|
||||
TableRow row1 = (TableRow) tableLayout.getChildAt(0);
|
||||
TextView row1Column2 = (TextView) row1.getChildAt(1);
|
||||
if (currentData != null) {
|
||||
row1Column2.setText(String.format("%.2f%%", currentData.getPercentFull()));
|
||||
|
||||
TableRow row2 = (TableRow) tableLayout.getChildAt(1);
|
||||
TextView row2Column2 = (TextView) row2.getChildAt(1);
|
||||
row2Column2.setText(String.format("%.2f", currentData.getWaterLevel()));
|
||||
|
||||
TableRow row3 = (TableRow) tableLayout.getChildAt(2);
|
||||
TextView row3Column2 = (TextView) row3.getChildAt(1);
|
||||
row3Column2.setText(String.format("%.2f", currentData.getSurfaceArea()));
|
||||
|
||||
TextView waterLevelValue = findViewById(R.id.waterLevelValue);
|
||||
TextView dateTime = findViewById(R.id.dateTime);
|
||||
TextView levelStatus = findViewById(R.id.levelStatus);
|
||||
|
||||
waterLevelValue.setText(String.format("%.2f", currentData.getWaterLevel()));
|
||||
dateTime.setText(currentData.getDate());
|
||||
levelStatus.setText(String.format("Level is %.2f feet below full pool of 909.00 ft", 909.00 - currentData.getWaterLevel()));
|
||||
} else {
|
||||
TextView waterLevelValue = findViewById(R.id.waterLevelValue);
|
||||
TextView dateTime = findViewById(R.id.dateTime);
|
||||
TextView levelStatus = findViewById(R.id.levelStatus);
|
||||
|
||||
waterLevelValue.setText("0.0");
|
||||
dateTime.setText("N/A");
|
||||
levelStatus.setText("No data available");
|
||||
|
||||
row1 = (TableRow) tableLayout.getChildAt(0);
|
||||
row1Column2 = (TextView) row1.getChildAt(1);
|
||||
row1Column2.setText("0.0%");
|
||||
|
||||
TableRow row2 = (TableRow) tableLayout.getChildAt(1);
|
||||
TextView row2Column2 = (TextView) row2.getChildAt(1);
|
||||
row2Column2.setText("0.0");
|
||||
|
||||
TableRow row3 = (TableRow) tableLayout.getChildAt(2);
|
||||
TextView row3Column2 = (TextView) row3.getChildAt(1);
|
||||
row3Column2.setText("0.0");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import edu.utsa.cs3443.lakewatch.model.WeatherData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class WeatherActivity extends AppCompatActivity {
|
||||
|
||||
private TextView weatherDescription;
|
||||
private TextView temperature;
|
||||
private TextView windDirection;
|
||||
private TextView windSpeed;
|
||||
private TextView windGust;
|
||||
private TextView chancePrecipitation;
|
||||
private TextView amountPrecipitation;
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_weather);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
weatherDescription = findViewById(R.id.weather_description);
|
||||
temperature = findViewById(R.id.temperature);
|
||||
windDirection = findViewById(R.id.wind_direction);
|
||||
windSpeed = findViewById(R.id.wind_speed);
|
||||
windGust = findViewById(R.id.wind_gust);
|
||||
chancePrecipitation = findViewById(R.id.chance_precipitation);
|
||||
amountPrecipitation = findViewById(R.id.amount_precipitation);
|
||||
|
||||
// Initialize the ExecutorService
|
||||
executorService = Executors.newSingleThreadExecutor();
|
||||
// Fetch weather data using ExecutorService
|
||||
fetchWeatherData();
|
||||
|
||||
Button weatherButton = findViewById(R.id.weather_button);
|
||||
weatherButton.setOnClickListener(v -> {
|
||||
String url = "https://forecast.weather.gov/MapClick.php?lat=29.699301&lon=-98.115109";
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
// Fetch weather data and update UI
|
||||
private void fetchWeatherData() {
|
||||
Callable<WeatherData> fetchWeatherTask = () -> {
|
||||
try {
|
||||
WeatherData weatherData = new WeatherData();
|
||||
WeatherData result = weatherData.loadWeatherData();
|
||||
Log.d("WeatherActivity", "WeatherData loaded: " + result);
|
||||
return result;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
Future<WeatherData> future = executorService.submit(fetchWeatherTask);
|
||||
|
||||
// Update the UI on the main thread
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
try {
|
||||
WeatherData weatherData = future.get();
|
||||
if (weatherData != null) {
|
||||
weatherData.saveWeatherData(WeatherActivity.this);
|
||||
updateUIWithWeatherData(weatherData);
|
||||
} else {
|
||||
weatherData = WeatherData.loadSavedWeatherData(WeatherActivity.this);
|
||||
if (weatherData != null) {
|
||||
updateUIWithWeatherData(weatherData);
|
||||
} else {
|
||||
weatherDescription.setText("No saved weather data available");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
weatherDescription.setText("Error fetching weather data");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUIWithWeatherData(WeatherData weatherData) {
|
||||
weatherDescription.setText(weatherData.getWeatherDescription());
|
||||
temperature.setText(String.format("H:%d°F L:%d°F", weatherData.getTempHigh(), weatherData.getTempLow()));
|
||||
String windDirectionValue = weatherData.getWindDirection();
|
||||
if (windDirectionValue.isEmpty()) {
|
||||
windDirectionValue = "N/A";
|
||||
}
|
||||
windDirection.setText(String.format("%s", windDirectionValue));
|
||||
windSpeed.setText(weatherData.getWindSpeed());
|
||||
windGust.setText(String.format("%.0f mph", weatherData.getWindGust()));
|
||||
chancePrecipitation.setText(String.format("%d%% Chance Precipitation", weatherData.getChancePrecipitation()));
|
||||
amountPrecipitation.setText(String.format("%.1f\u2033 Precipitation Next 24 HR", weatherData.getAmountPrecipitation()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
// Shut down the ExecutorService when the activity is destroyed
|
||||
if (executorService != null && !executorService.isShutdown()) {
|
||||
executorService.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,318 @@
|
||||
package edu.utsa.cs3443.lakewatch.model;
|
||||
|
||||
import android.content.Context;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Serializable;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Model class containing logic and data for all boat ramps
|
||||
*
|
||||
*/
|
||||
public class BoatRampData implements Serializable {
|
||||
private Integer rampNumber;
|
||||
private String name;
|
||||
private BoatRampStatus status;
|
||||
private String openTimes;
|
||||
private String address;
|
||||
private String operator;
|
||||
private LocalDate lastUpdated;
|
||||
|
||||
private static final String CACHE_FILE_NAME = "BoatRampData.json";
|
||||
|
||||
/**
|
||||
* Create a single boat ramp instance
|
||||
*
|
||||
* @param rampNumber The official ramp number
|
||||
* @param name The more commonly known name of the ramp
|
||||
* @param status The open/closed/unknown status of the ramp
|
||||
* @param openTimes The times the ramp can be used if its status is "open"
|
||||
* @param address The approximate address of the ramp
|
||||
* @param operator The owner of the ramp, like Comal County
|
||||
* @param lastUpdated The last time the given data was updated
|
||||
*/
|
||||
public BoatRampData(
|
||||
Integer rampNumber,
|
||||
String name,
|
||||
BoatRampStatus status,
|
||||
String openTimes,
|
||||
String address,
|
||||
String operator,
|
||||
LocalDate lastUpdated) {
|
||||
this.setRampNumber(rampNumber);
|
||||
this.setName(name);
|
||||
this.setStatus(status);
|
||||
this.setOpenTimes(openTimes);
|
||||
this.setAddress(address);
|
||||
this.setOperator(operator);
|
||||
this.setLastUpdated(lastUpdated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the common name of the ramp
|
||||
*
|
||||
* @return name of the ramp
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the common name of the ramp
|
||||
*
|
||||
* @param name common name of the ramp
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the open/closed/unknown status of the ramp
|
||||
*
|
||||
* @return status of the ramp
|
||||
*/
|
||||
public BoatRampStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the open/closed/unknown status of the ramp
|
||||
*
|
||||
* @param status new status for the ramp
|
||||
*/
|
||||
public void setStatus(BoatRampStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the operating times of the ramp
|
||||
*
|
||||
* @return operating times of the ramp
|
||||
*/
|
||||
public String getOpenTimes() {
|
||||
return openTimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the operating times of the ramp
|
||||
*
|
||||
* @param openTimes new operating times for the ramp
|
||||
*/
|
||||
public void setOpenTimes(String openTimes) {
|
||||
this.openTimes = openTimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the approximate address of the ramp
|
||||
*
|
||||
* @return address of the ramp
|
||||
*/
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address of the ramp
|
||||
*
|
||||
* @param address new address for the ramp
|
||||
*/
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the operator of the ramp
|
||||
*
|
||||
* @return operator of the ramp
|
||||
*/
|
||||
public String getOperator() {
|
||||
return operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the operator of the ramp
|
||||
*
|
||||
* @param operator new operator for the ramp
|
||||
*/
|
||||
public void setOperator(String operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last time the given data set was updated
|
||||
*
|
||||
* @return last updated time for the ramp data
|
||||
*/
|
||||
public LocalDate getLastUpdated() {
|
||||
return lastUpdated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the last updated time for the ramp
|
||||
*
|
||||
* @param lastUpdated new update time for the ramp's data
|
||||
*/
|
||||
public void setLastUpdated(LocalDate lastUpdated) {
|
||||
this.lastUpdated = lastUpdated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full listing of all the ramp's data from a JSON Array
|
||||
*
|
||||
* @param in The json stream to parse
|
||||
* @return A full listing of boat ramp data
|
||||
* @throws IOException when readers cannot be created
|
||||
* @throws JSONException when the input stream contains invalid json
|
||||
*/
|
||||
private static ArrayList<BoatRampData> fromJsonStream(InputStream in)
|
||||
throws IOException, JSONException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
StringBuilder out = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
}
|
||||
reader.close();
|
||||
ArrayList<BoatRampData> rampData = new ArrayList<>();
|
||||
JSONArray json = new JSONArray(out.toString());
|
||||
for (int i = 0; i < json.length(); i++) {
|
||||
JSONObject rampJson = json.getJSONObject(i);
|
||||
rampData.add(BoatRampData.fromJson(rampJson));
|
||||
}
|
||||
|
||||
rampData.sort(Comparator.comparing(BoatRampData::getStatus));
|
||||
return rampData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the latest ramp data from the API
|
||||
*
|
||||
* @return An updated full listing of all boat ramp data
|
||||
* @throws Exception When the request fails in any shape way or form
|
||||
*/
|
||||
public static ArrayList<BoatRampData> fetchData() throws Exception {
|
||||
HttpURLConnection conn =
|
||||
(HttpURLConnection)
|
||||
new URL("https://lakewatch.orion-technologies.io/v1/ramps").openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setRequestProperty("Accept", "application/json");
|
||||
return BoatRampData.fromJsonStream(conn.getInputStream());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load's the data from a cached file on disk if it exists
|
||||
*
|
||||
* @param context a given android context, used to lookup common paths
|
||||
* @return The last cached full listing of all boat ramp data
|
||||
* @throws IOException If the cache file cannot be read or doesn't exist
|
||||
* @throws JSONException If the data contained within the file is invalid
|
||||
*/
|
||||
public static ArrayList<BoatRampData> loadCachedData(Context context)
|
||||
throws IOException, JSONException {
|
||||
File file = new File(context.getCacheDir(), BoatRampData.CACHE_FILE_NAME);
|
||||
return BoatRampData.fromJsonStream(Files.newInputStream(file.toPath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wipe the cache file on disk
|
||||
*
|
||||
* @param context the android context used to look up the cache directory
|
||||
* @throws IOException If the file cannot be deleted and it exists
|
||||
*/
|
||||
public static void wipeCache(Context context) throws IOException {
|
||||
File file = new File(context.getCacheDir(), BoatRampData.CACHE_FILE_NAME);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a ramp's data into JSON for export
|
||||
*
|
||||
* @return The json representation of the ramp
|
||||
* @throws JSONException If it's not possible to parse the ramp data into JSON
|
||||
*/
|
||||
public JSONObject toJson() throws JSONException {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("number", this.getRampNumber());
|
||||
json.put("name", this.getName());
|
||||
json.put("address", this.getAddress());
|
||||
json.put("operator", this.getOperator());
|
||||
json.put("status", this.getStatus().toString());
|
||||
json.put(
|
||||
"last_updated", this.getLastUpdated().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
json.put("operating_times", this.getOpenTimes());
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a given ramp's data from JSON
|
||||
*
|
||||
* @param json The json object to deserialize
|
||||
* @return A single boat ramp's data
|
||||
* @throws JSONException If the data contains invalid json
|
||||
*/
|
||||
public static BoatRampData fromJson(JSONObject json) throws JSONException {
|
||||
Integer rampNumber = json.getInt("number");
|
||||
String name = json.getString("name");
|
||||
String address = json.getString("address");
|
||||
String operator = json.getString("operator");
|
||||
BoatRampStatus status = BoatRampStatus.fromString(json.getString("status"));
|
||||
LocalDate lastUpdated = LocalDate.parse(json.getString("last_updated"));
|
||||
String openTimes = json.getString("operating_times");
|
||||
return new BoatRampData(rampNumber, name, status, openTimes, address, operator, lastUpdated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a full listing of ramp data to a cache file on disk
|
||||
*
|
||||
* @param context Used to get android paths on the file system
|
||||
* @param rampData The full listing of ramp data to save
|
||||
* @throws IOException If the cache file cannot be written to
|
||||
* @throws JSONException If the ramp data cannot be serialized into JSON
|
||||
*/
|
||||
public static void saveData(Context context, ArrayList<BoatRampData> rampData)
|
||||
throws IOException, JSONException {
|
||||
File file = new File(context.getCacheDir(), BoatRampData.CACHE_FILE_NAME);
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(file.getAbsoluteFile()));
|
||||
JSONArray jsonData = new JSONArray();
|
||||
for (BoatRampData ramp : rampData) {
|
||||
jsonData.put(ramp.toJson());
|
||||
}
|
||||
bw.write(jsonData.toString());
|
||||
bw.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the ramp
|
||||
*
|
||||
* @return number of the ramp
|
||||
*/
|
||||
public Integer getRampNumber() {
|
||||
return rampNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new number for the ramp
|
||||
*
|
||||
* @param rampNumber new number for the ramp
|
||||
*/
|
||||
public void setRampNumber(Integer rampNumber) {
|
||||
this.rampNumber = rampNumber;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package edu.utsa.cs3443.lakewatch.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public enum BoatRampStatus implements Serializable {
|
||||
OPEN,
|
||||
CLOSED,
|
||||
UNKNOWN;
|
||||
|
||||
/**
|
||||
* Get the string representation of the current Enum
|
||||
*/
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case OPEN:
|
||||
return "Open";
|
||||
case CLOSED:
|
||||
return "Closed";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boat ramp status from a String
|
||||
*
|
||||
* @param status The string to convert to a status enum
|
||||
*/
|
||||
public static BoatRampStatus fromString(String status) {
|
||||
switch (status.toLowerCase()) {
|
||||
case "open":
|
||||
return BoatRampStatus.OPEN;
|
||||
case "closed":
|
||||
return BoatRampStatus.CLOSED;
|
||||
default:
|
||||
return BoatRampStatus.UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,324 @@
|
||||
package edu.utsa.cs3443.lakewatch.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class WaterLevelData {
|
||||
|
||||
private Date date;
|
||||
private double waterLevel;
|
||||
private double surfaceArea;
|
||||
private int reservoirStorage;
|
||||
private int conservationStorage;
|
||||
private double percentFull;
|
||||
private int conservationCapacity;
|
||||
private int deadPoolCapacity;
|
||||
private boolean isCurrent;
|
||||
|
||||
|
||||
public WaterLevelData(Date date, double waterLevel, boolean isCurrent) {
|
||||
this.date = date;
|
||||
this.waterLevel = waterLevel;
|
||||
this.isCurrent = isCurrent;
|
||||
this.surfaceArea = 0.0;
|
||||
this.reservoirStorage = 0;
|
||||
this.conservationStorage = 0;
|
||||
this.percentFull = 0.0;
|
||||
this.conservationCapacity = 0;
|
||||
this.deadPoolCapacity = 0;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getDate() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public double getWaterLevel() {
|
||||
return waterLevel;
|
||||
}
|
||||
|
||||
public void setWaterLevel(double waterLevel) {
|
||||
this.waterLevel = waterLevel;
|
||||
}
|
||||
|
||||
public double getSurfaceArea() {
|
||||
return surfaceArea;
|
||||
}
|
||||
|
||||
public void setSurfaceArea(double surfaceArea) {
|
||||
this.surfaceArea = surfaceArea;
|
||||
}
|
||||
|
||||
public int getReservoirStorage() {
|
||||
return reservoirStorage;
|
||||
}
|
||||
|
||||
public void setReservoirStorage(int reservoirStorage) {
|
||||
this.reservoirStorage = reservoirStorage;
|
||||
}
|
||||
|
||||
public int getConservationStorage() {
|
||||
return conservationStorage;
|
||||
}
|
||||
|
||||
public void setConservationStorage(int conservationStorage) {
|
||||
this.conservationStorage = conservationStorage;
|
||||
}
|
||||
|
||||
public double getPercentFull() {
|
||||
return percentFull;
|
||||
}
|
||||
|
||||
public void setPercentFull(double percentFull) {
|
||||
this.percentFull = percentFull;
|
||||
}
|
||||
|
||||
public int getConservationCapacity() {
|
||||
return conservationCapacity;
|
||||
}
|
||||
|
||||
public void setConservationCapacity(int conservationCapacity) {
|
||||
this.conservationCapacity = conservationCapacity;
|
||||
}
|
||||
|
||||
public int getDeadPoolCapacity() {
|
||||
return deadPoolCapacity;
|
||||
}
|
||||
|
||||
public void setDeadPoolCapacity(int deadPoolCapacity) {
|
||||
this.deadPoolCapacity = deadPoolCapacity;
|
||||
}
|
||||
|
||||
public boolean isCurrent() {
|
||||
return isCurrent;
|
||||
}
|
||||
|
||||
public void setCurrent(boolean isCurrent) {
|
||||
this.isCurrent = isCurrent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WaterLevelData{" +
|
||||
"date=" + date +
|
||||
", waterLevel=" + waterLevel +
|
||||
", surfaceArea=" + surfaceArea +
|
||||
", reservoirStorage=" + reservoirStorage +
|
||||
", conservationStorage=" + conservationStorage +
|
||||
", percentFull=" + percentFull +
|
||||
", conservationCapacity=" + conservationCapacity +
|
||||
", deadPoolCapacity=" + deadPoolCapacity +
|
||||
", isCurrent=" + isCurrent +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static String getJsonResponseFromApi() {
|
||||
String urlString = "https://lakewatch.orion-technologies.io/v1/waterdata?start=1900-01-01&end=3000-01-01"; //API URL
|
||||
HttpURLConnection urlConnection = null;
|
||||
BufferedReader reader = null;
|
||||
String jsonResponse = null;
|
||||
|
||||
try {
|
||||
URL url = new URL(urlString);
|
||||
urlConnection = (HttpURLConnection) url.openConnection();
|
||||
urlConnection.setRequestMethod("GET");
|
||||
urlConnection.connect();
|
||||
|
||||
InputStream inputStream = urlConnection.getInputStream();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if (inputStream == null) {
|
||||
return null;
|
||||
}
|
||||
reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
buffer.append(line).append("\n");
|
||||
}
|
||||
|
||||
if (buffer.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
jsonResponse = buffer.toString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jsonResponse;
|
||||
}
|
||||
|
||||
|
||||
public static WaterLevelData _loadWaterLevelData(String jsonResponse) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
||||
|
||||
try {
|
||||
JSONArray jsonArray = new JSONArray(jsonResponse);
|
||||
if (jsonArray.length() > 0) {
|
||||
JSONObject jsonObject = jsonArray.getJSONObject(jsonArray.length() - 1); // Get the last entry
|
||||
|
||||
Date date;
|
||||
try {
|
||||
date = sdf.parse(jsonObject.getString("date"));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
date = new Date(); // Default to current date if parsing fails
|
||||
}
|
||||
|
||||
double waterLevel = jsonObject.optDouble("water_level", 0.0);
|
||||
|
||||
WaterLevelData data = new WaterLevelData(date, waterLevel, true);
|
||||
|
||||
data.setSurfaceArea(jsonObject.optDouble("surface_area", 0.0));
|
||||
data.setReservoirStorage(jsonObject.optInt("reservoir_storage", 0));
|
||||
data.setConservationStorage(jsonObject.optInt("conservation_storage", 0));
|
||||
data.setPercentFull(jsonObject.optDouble("percent_full", 0.0));
|
||||
data.setConservationCapacity(jsonObject.optInt("conservation_capacity", 0));
|
||||
data.setDeadPoolCapacity(jsonObject.optInt("dead_pool_capacity", 0));
|
||||
|
||||
return data;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null; // Return null if no data is available
|
||||
}
|
||||
|
||||
|
||||
// Save the data to a JSON file
|
||||
public void saveWaterLevelData(Context context) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
|
||||
try {
|
||||
jsonObject.put("date", sdf.format(date));
|
||||
jsonObject.put("water_level", waterLevel);
|
||||
jsonObject.put("surface_area", surfaceArea);
|
||||
jsonObject.put("reservoir_storage", reservoirStorage);
|
||||
jsonObject.put("conservation_storage", conservationStorage);
|
||||
jsonObject.put("percent_full", percentFull);
|
||||
jsonObject.put("conservation_capacity", conservationCapacity);
|
||||
jsonObject.put("dead_pool_capacity", deadPoolCapacity);
|
||||
|
||||
File file = new File(context.getFilesDir(), "water_level_data.json");
|
||||
FileWriter fileWriter = new FileWriter(file);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
bufferedWriter.write(jsonObject.toString());
|
||||
bufferedWriter.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("WaterLevelData", "Failed to save data", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the data from a JSON file
|
||||
public static WaterLevelData loadSavedWaterLevelData(Context context) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
||||
File file = new File(context.getFilesDir(), "water_level_data.json");
|
||||
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
FileReader fileReader = new FileReader(file);
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
StringBuilder jsonBuilder = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
jsonBuilder.append(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
JSONObject jsonObject = new JSONObject(jsonBuilder.toString());
|
||||
|
||||
Date date;
|
||||
try {
|
||||
date = sdf.parse(jsonObject.getString("date"));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
date = new Date(); // Default to current date if parsing fails
|
||||
}
|
||||
|
||||
double waterLevel = jsonObject.optDouble("water_level", 0.0);
|
||||
|
||||
WaterLevelData data = new WaterLevelData(date, waterLevel, true);
|
||||
|
||||
data.setSurfaceArea(jsonObject.optDouble("surface_area", 0.0));
|
||||
data.setReservoirStorage(jsonObject.optInt("reservoir_storage", 0));
|
||||
data.setConservationStorage(jsonObject.optInt("conservation_storage", 0));
|
||||
data.setPercentFull(jsonObject.optDouble("percent_full", 0.0));
|
||||
data.setConservationCapacity(jsonObject.optInt("conservation_capacity", 0));
|
||||
data.setDeadPoolCapacity(jsonObject.optInt("dead_pool_capacity", 0));
|
||||
|
||||
return data;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("WaterLevelData", "Failed to load data", e);
|
||||
}
|
||||
|
||||
return null; // Return null if loading fails
|
||||
}
|
||||
|
||||
// Clear cached data
|
||||
public static void clearCache(Context context) {
|
||||
File file = new File(context.getFilesDir(), "water_level_data.json");
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Force data fetch
|
||||
public static void forceDataFetch(Context context) {
|
||||
new Thread(() -> {
|
||||
String jsonResponse = getJsonResponseFromApi();
|
||||
if (jsonResponse != null) {
|
||||
WaterLevelData data = _loadWaterLevelData(jsonResponse);
|
||||
if (data != null) {
|
||||
data.saveWaterLevelData(context);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,382 @@
|
||||
package edu.utsa.cs3443.lakewatch.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Represents the weather data for a specified location. This class holds various weather attributes
|
||||
* such as temperature, wind speed, wind direction, and precipitation amounts.
|
||||
* It provides methods to load weather data from a remote API and populate its fields accordingly.
|
||||
*
|
||||
* The weather data includes:
|
||||
* - Weather description
|
||||
* - High and low temperatures
|
||||
* - Wind speed and gust
|
||||
* - Wind direction
|
||||
* - Chance of precipitation
|
||||
* - Amount of precipitation
|
||||
*
|
||||
* @author Ethan Grams - bib016
|
||||
*/
|
||||
public class WeatherData {
|
||||
|
||||
private String weatherDescription;
|
||||
private int tempHigh;
|
||||
private int tempLow;
|
||||
private String windSpeed;
|
||||
private double windGust;
|
||||
private String windDirection;
|
||||
private int chancePrecipitation;
|
||||
private double amountPrecipitation;
|
||||
|
||||
private static final String CACHE_FILE_NAME = "weather_data.json";
|
||||
|
||||
// Constructor with all fields
|
||||
public WeatherData(String weatherDescription, int tempHigh, int tempLow, String windSpeed, double windGust, String windDirection, int chancePrecipitation, double amountPrecipitation) {
|
||||
this.weatherDescription = weatherDescription;
|
||||
this.tempHigh = tempHigh;
|
||||
this.tempLow = tempLow;
|
||||
this.windSpeed = windSpeed;
|
||||
this.windGust = windGust;
|
||||
this.windDirection = windDirection;
|
||||
this.chancePrecipitation = chancePrecipitation;
|
||||
this.amountPrecipitation = amountPrecipitation;
|
||||
}
|
||||
|
||||
// Default Constructor
|
||||
public WeatherData() {}
|
||||
|
||||
/**
|
||||
* Loads weather data from the weather.gov API and creates a WeatherData object.
|
||||
* This method fetches both hourly and general weather data for a specified weather station,
|
||||
* populating the fields of the WeatherData object with the retrieved information.
|
||||
*
|
||||
* @return a WeatherData object populated with the fetched weather data
|
||||
* @throws IOException if there is an error during the network connection or data retrieval
|
||||
*/
|
||||
public WeatherData loadWeatherData() throws IOException {
|
||||
WeatherData weatherData = new WeatherData();
|
||||
|
||||
String hourlyUrl = "https://api.weather.gov/gridpoints/EWX/136,74/forecast/hourly";
|
||||
String generalUrl = "https://api.weather.gov/gridpoints/EWX/136,74";
|
||||
|
||||
// Fetch hourly weather data
|
||||
fetchHourlyWeatherData(hourlyUrl, weatherData);
|
||||
|
||||
// Fetch general weather data
|
||||
fetchGeneralWeatherData(generalUrl, weatherData);
|
||||
|
||||
return weatherData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches and processes hourly weather data for a specified weather station.
|
||||
* Establishes a connection to the given URL, retrieves the weather data in JSON format,
|
||||
* and extracts the necessary values to populate the provided WeatherData object.
|
||||
* Handles weather description, wind speed and direction, and chance of precipitation.
|
||||
*
|
||||
* @param url the URL to fetch weather data from
|
||||
* @param weatherData the WeatherData object to populate with the fetched data
|
||||
* @throws IOException if there is an error during the network connection or data retrieval
|
||||
*/
|
||||
private void fetchHourlyWeatherData(String url, WeatherData weatherData) throws IOException {
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
|
||||
try {
|
||||
setupConnection(urlConnection);
|
||||
|
||||
int responseCode = urlConnection.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
String response = readStream(urlConnection.getInputStream());
|
||||
JSONObject jsonResponse = new JSONObject(response);
|
||||
JSONArray periods = jsonResponse.getJSONObject("properties").getJSONArray("periods");
|
||||
JSONObject firstPeriod = periods.getJSONObject(0);
|
||||
|
||||
weatherData.setWeatherDescription(firstPeriod.getString("shortForecast"));
|
||||
weatherData.setWindSpeed(firstPeriod.getString("windSpeed"));
|
||||
weatherData.setWindDirection(firstPeriod.getString("windDirection"));
|
||||
weatherData.setChancePrecipitation(firstPeriod.getJSONObject("probabilityOfPrecipitation").optInt("value", 0));
|
||||
} else {
|
||||
throw new IOException("HTTP error code: " + responseCode);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches and processes general weather data for a specified weather station.
|
||||
* Establishes a connection to the given URL, retrieves the weather data in JSON format,
|
||||
* and extracts the necessary values to populate the provided WeatherData object.
|
||||
* Handles high and low temperatures, wind gusts, and precipitation amounts,
|
||||
* converting units as necessary.
|
||||
*
|
||||
* @param url the URL to fetch weather data from
|
||||
* @param weatherData the WeatherData object to populate with the fetched data
|
||||
* @throws IOException if there is an error during the network connection or data retrieval
|
||||
*/
|
||||
private void fetchGeneralWeatherData(String url, WeatherData weatherData) throws IOException {
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
|
||||
try {
|
||||
setupConnection(urlConnection);
|
||||
|
||||
int responseCode = urlConnection.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
String response = readStream(urlConnection.getInputStream());
|
||||
JSONObject jsonResponse = new JSONObject(response);
|
||||
JSONObject properties = jsonResponse.getJSONObject("properties");
|
||||
|
||||
weatherData.setTempHigh(convertToFahrenheit(getMaxTemp(properties.getJSONObject("maxTemperature").getJSONArray("values"))));
|
||||
weatherData.setTempLow(convertToFahrenheit(getMinTemp(properties.getJSONObject("minTemperature").getJSONArray("values"))));
|
||||
weatherData.setWindGust(convertKmhToMph(properties.getJSONObject("windGust").getJSONArray("values").getJSONObject(0).optInt("value")));
|
||||
weatherData.setAmountPrecipitation(convertMmToInches(sumPrecipitation(properties.getJSONObject("quantitativePrecipitation").getJSONArray("values"), 4)));
|
||||
} else {
|
||||
throw new IOException("HTTP error code: " + responseCode);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the given HttpURLConnection with the necessary request properties.
|
||||
* Sets the request method to GET, and specifies that the response should be in JSON format.
|
||||
* Also sets the User-Agent to mimic a modern web browser.
|
||||
*
|
||||
* @param connection the HttpURLConnection to be configured
|
||||
* @throws ProtocolException if there is an error in the underlying protocol
|
||||
*/
|
||||
private void setupConnection(HttpURLConnection connection) throws ProtocolException {
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");
|
||||
}
|
||||
|
||||
// Reads in data and returns it in one String
|
||||
private String readStream(InputStream in) throws IOException {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
StringBuilder out = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
}
|
||||
reader.close();
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
// Takes two high temperatures within a 24 hour period and returns the maximum
|
||||
private int getMaxTemp(JSONArray values) throws JSONException {
|
||||
return Math.max(values.getJSONObject(0).optInt("value", 0), values.getJSONObject(1).optInt("value", 0));
|
||||
}
|
||||
|
||||
// Returns the current low temperature
|
||||
private int getMinTemp(JSONArray values) throws JSONException {
|
||||
return values.getJSONObject(0).optInt("value", 0);
|
||||
}
|
||||
|
||||
// Sums precipitation over a 24 hour period
|
||||
private double sumPrecipitation(JSONArray values, int count) throws JSONException {
|
||||
double sum = 0.0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
sum += values.getJSONObject(i).optInt("value", 0);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
// Converts Celsius to Fahrenheit
|
||||
private int convertToFahrenheit(int celsius) {
|
||||
return (int) (celsius * (9.0 / 5.0)) + 32;
|
||||
}
|
||||
|
||||
// Converts Kilometers Per Hour to Miles Per Hour
|
||||
private double convertKmhToMph(double kmh) {
|
||||
return kmh * 0.621371;
|
||||
}
|
||||
|
||||
// Converts millimeters to inches
|
||||
private double convertMmToInches(double mm) {
|
||||
return mm * 0.0393701;
|
||||
}
|
||||
|
||||
// Save the data to a JSON file
|
||||
public void saveWeatherData(Context context) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("weather_description", weatherDescription);
|
||||
jsonObject.put("temp_high", tempHigh);
|
||||
jsonObject.put("temp_low", tempLow);
|
||||
jsonObject.put("wind_speed", windSpeed);
|
||||
jsonObject.put("wind_gust", windGust);
|
||||
jsonObject.put("wind_direction", windDirection);
|
||||
jsonObject.put("chance_precipitation", chancePrecipitation);
|
||||
jsonObject.put("amount_precipitation", amountPrecipitation);
|
||||
File file = new File(context.getFilesDir(), "weather_data.json");
|
||||
FileWriter fileWriter = new FileWriter(file);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||
bufferedWriter.write(jsonObject.toString());
|
||||
bufferedWriter.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("WaterLevelData", "Failed to save data", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the data from a JSON file
|
||||
public static WeatherData loadSavedWeatherData(Context context) {
|
||||
File file = new File(context.getFilesDir(), "weather_data.json");
|
||||
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
FileReader fileReader = new FileReader(file);
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
StringBuilder jsonBuilder = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
jsonBuilder.append(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
JSONObject jsonObject = new JSONObject(jsonBuilder.toString());
|
||||
|
||||
|
||||
double waterLevel = jsonObject.optDouble("water_level", 0.0);
|
||||
|
||||
WeatherData weatherData = new WeatherData();
|
||||
|
||||
weatherData.setWeatherDescription(jsonObject.optString("weather_description", ""));
|
||||
weatherData.setTempHigh(jsonObject.optInt("temp_high", 0));
|
||||
weatherData.setTempLow(jsonObject.optInt("temp_low", 0));
|
||||
weatherData.setWindSpeed(jsonObject.optString("wind_speed", ""));
|
||||
weatherData.setWindGust(jsonObject.optDouble("wind_gust", 0.0));
|
||||
weatherData.setWindDirection(jsonObject.optString("wind_direction", ""));
|
||||
weatherData.setChancePrecipitation(jsonObject.optInt("chance_precipitation", 0));
|
||||
weatherData.setAmountPrecipitation(jsonObject.optDouble("amount_precipitation", 0.0));
|
||||
|
||||
return weatherData;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("WeatherData", "Failed to load data", e);
|
||||
}
|
||||
|
||||
return null; // Return null if loading fails
|
||||
}
|
||||
|
||||
/**
|
||||
* Wipe the cache file on disk
|
||||
*
|
||||
* @param context the android context used to look up the cache directory
|
||||
* @throws IOException If the file cannot be deleted and it exists
|
||||
*/
|
||||
public static void wipeCache(Context context) throws IOException {
|
||||
File file = new File(context.getCacheDir(), WeatherData.CACHE_FILE_NAME);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeatherData{" +
|
||||
"weatherDescription='" + weatherDescription + '\'' +
|
||||
", tempHigh=" + tempHigh +
|
||||
", tempLow=" + tempLow +
|
||||
", windSpeed='" + windSpeed + '\'' +
|
||||
", windGust=" + windGust +
|
||||
", windDirection='" + windDirection + '\'' +
|
||||
", chancePrecipitation=" + chancePrecipitation +
|
||||
", amountPrecipitation=" + amountPrecipitation +
|
||||
'}';
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getWeatherDescription() {
|
||||
return weatherDescription;
|
||||
}
|
||||
|
||||
public void setWeatherDescription(String weatherDescription) {
|
||||
this.weatherDescription = weatherDescription;
|
||||
}
|
||||
|
||||
public int getTempHigh() {
|
||||
return tempHigh;
|
||||
}
|
||||
|
||||
public void setTempHigh(int tempHigh) {
|
||||
this.tempHigh = tempHigh;
|
||||
}
|
||||
|
||||
public int getTempLow() {
|
||||
return tempLow;
|
||||
}
|
||||
|
||||
public void setTempLow(int tempLow) {
|
||||
this.tempLow = tempLow;
|
||||
}
|
||||
|
||||
public String getWindSpeed() {
|
||||
return windSpeed;
|
||||
}
|
||||
|
||||
public void setWindSpeed(String windSpeed) {
|
||||
this.windSpeed = windSpeed;
|
||||
}
|
||||
|
||||
public double getWindGust() {
|
||||
return windGust;
|
||||
}
|
||||
|
||||
public void setWindGust(double windGust) {
|
||||
this.windGust = windGust;
|
||||
}
|
||||
|
||||
public String getWindDirection() {
|
||||
return windDirection;
|
||||
}
|
||||
|
||||
public void setWindDirection(String windDirection) {
|
||||
this.windDirection = windDirection;
|
||||
}
|
||||
|
||||
public int getChancePrecipitation() {
|
||||
return chancePrecipitation;
|
||||
}
|
||||
|
||||
public void setChancePrecipitation(int chancePrecipitation) {
|
||||
this.chancePrecipitation = chancePrecipitation;
|
||||
}
|
||||
|
||||
public double getAmountPrecipitation() {
|
||||
return amountPrecipitation;
|
||||
}
|
||||
|
||||
public void setAmountPrecipitation(double amountPrecipitation) {
|
||||
this.amountPrecipitation = amountPrecipitation;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package edu.utsa.cs3443.lakewatch.model;
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
/**
|
||||
* This class is referenced on line 6
|
||||
* of the AndroidManifest.XML to implement
|
||||
* dark mode universally within the app's views
|
||||
* @author Gavin Diab
|
||||
*/
|
||||
public class userSettings extends Application {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// Load the theme setting from SharedPreferences
|
||||
SharedPreferences sharedPreferences = getSharedPreferences("sharedPrefs", MODE_PRIVATE);
|
||||
boolean isDarkModeOn = sharedPreferences.getBoolean("isDarkModeOn", false);
|
||||
|
||||
// Apply the theme setting
|
||||
if (isDarkModeOn) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
} else {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="50"
|
||||
android:viewportHeight="50">
|
||||
<path
|
||||
android:pathData="M8.5,7.092l9.565,2.639 5.309,-3.731 1.847,0.455 -5.259,3.742 28.985,8.053 -2.121,7.882 -29.093,-8.031c-11.271,-3.399 -9.216,-11.009 -9.216,-11.009"
|
||||
android:fillColor="?attr/colorControlNormal"/>
|
||||
<path
|
||||
android:pathData="M33.957,27.258c-0.035,-0.658 -0.16,-1.285 -0.375,-1.877l13.281,3.697 -0.426,1.639 -12.48,-3.459zM21.891,23.926c0.358,-0.521 0.782,-0.991 1.264,-1.398l-22.155,-6.12v1.763l20.891,5.755zM27.377,29.762c1.191,0 2.158,-0.969 2.158,-2.16 0,-1.195 -0.967,-2.162 -2.158,-2.162 -1.195,0 -2.161,0.967 -2.161,2.162 0,1.191 0.966,2.16 2.161,2.16zM49,43c-1.051,0 -2.051,-0.238 -2.943,-0.648 -0.928,-0.42 -1.963,-0.672 -3.047,-0.672 -1.08,0 -2.121,0.252 -3.035,0.672 -0.905,0.41 -1.903,0.648 -2.955,0.648 -1.051,0 -2.053,-0.238 -2.955,-0.648 -0.92,-0.42 -1.953,-0.672 -3.035,-0.672 -1.086,0 -2.119,0.252 -3.045,0.672 -0.893,0.41 -1.905,0.648 -2.951,0.648 -1.045,0 -2.051,-0.238 -2.949,-0.648 -0.926,-0.42 -1.967,-0.672 -3.046,-0.672 -1.08,0 -2.12,0.252 -3.035,0.672 -0.898,0.41 -1.909,0.648 -2.956,0.648 -1.045,0 -2.051,-0.238 -2.955,-0.648 -0.916,-0.42 -1.956,-0.672 -3.036,-0.672 -1.079,0 -2.119,0.252 -3.04,0.672 -0.897,0.41 -1.909,0.648 -2.949,0.648l-0.068,-17.605 24.227,6.686c-1.67,-0.807 -2.83,-2.5 -2.83,-4.479 0,-2.754 2.227,-4.983 4.979,-4.983 2.744,0 4.977,2.229 4.977,4.983 0,2.752 -2.232,4.98 -4.977,4.98l-0.49,-0.047 22.078,6.088 0.036,4.377z"
|
||||
android:fillColor="?attr/colorControlNormal"/>
|
||||
</vector>
|
@ -0,0 +1,81 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512.35dp"
|
||||
android:height="512.35dp"
|
||||
android:viewportWidth="512.35"
|
||||
android:viewportHeight="512.35">
|
||||
<path
|
||||
android:pathData="M256.17,256.17m-255.17,0a255.17,255.17 0,1 1,510.35 0a255.17,255.17 0,1 1,-510.35 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#f2fbb7"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="m92.23,143.09h327.89a10,10 45,0 1,10 10v227.89a10,10 135,0 1,-10 10L92.23,390.98a10,10 45,0 1,-10 -10L82.23,153.09a10,10 135,0 1,10 -10z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2.10845"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M87.39,135.48L424.96,135.48a10,10 45,0 1,10 10v17.57a10,10 135,0 1,-10 10L87.39,173.05a10,10 45,0 1,-10 -10v-17.57a10,10 135,0 1,10 -10z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2.42674"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M107.23,142.67a16.44,26.44 0,1 0,32.89 0a16.44,26.44 0,1 0,-32.89 0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2.11426"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M372.23,142.67a16.44,26.44 0,1 0,32.89 0a16.44,26.44 0,1 0,-32.89 0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2.11426"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m139.19,200h61.32a4,4 45,0 1,4 4v61.32a4,4 135,0 1,-4 4h-61.32a4,4 45,0 1,-4 -4v-61.32a4,4 135,0 1,4 -4z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m311.83,200h61.32a4,4 45,0 1,4 4v61.32a4,4 135,0 1,-4 4h-61.32a4,4 45,0 1,-4 -4v-61.32a4,4 135,0 1,4 -4z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m225.51,286.32h61.32a4,4 45,0 1,4 4v61.32a4,4 135,0 1,-4 4h-61.32a4,4 45,0 1,-4 -4v-61.32a4,4 135,0 1,4 -4z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m225.51,200h61.32a4,4 45,0 1,4 4v61.32a4,4 135,0 1,-4 4h-61.32a4,4 45,0 1,-4 -4v-61.32a4,4 135,0 1,4 -4z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m139.19,286.32h61.32a4,4 45,0 1,4 4v61.32a4,4 135,0 1,-4 4h-61.32a4,4 45,0 1,-4 -4v-61.32a4,4 135,0 1,4 -4z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="m311.83,286.32h61.32a4,4 45,0 1,4 4v61.32a4,4 135,0 1,-4 4h-61.32a4,4 45,0 1,-4 -4v-61.32a4,4 135,0 1,4 -4z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
</vector>
|
@ -0,0 +1,16 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512.35dp"
|
||||
android:height="512.35dp"
|
||||
android:viewportWidth="512.35"
|
||||
android:viewportHeight="512.35">
|
||||
<path
|
||||
android:pathData="M256.17,256.17m-255.17,0a255.17,255.17 0,1 1,510.35 0a255.17,255.17 0,1 1,-510.35 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#72F18A"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="m345.65,142.86 l-136.43,136.43 -42.83,-42.83 -44.94,44.94 88.09,88.09 0.35,-0.35 44.59,-44.59h0L390.9,188.11Z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
@ -0,0 +1,25 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512.35dp"
|
||||
android:height="512.35dp"
|
||||
android:viewportWidth="512.35"
|
||||
android:viewportHeight="512.35">
|
||||
<path
|
||||
android:pathData="M256.17,256.17m-255.17,0a255.17,255.17 0,1 1,510.35 0a255.17,255.17 0,1 1,-510.35 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#b7f8fb"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M147.58,131.93l232.62,0l0,232.62l-232.62,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="7.96"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M132.15,147.8l232.62,0l0,232.62l-232.62,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="7.96"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
</vector>
|
@ -0,0 +1,16 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512.35dp"
|
||||
android:height="512.35dp"
|
||||
android:viewportWidth="512.35"
|
||||
android:viewportHeight="512.35">
|
||||
<path
|
||||
android:pathData="M256.17,256.17m-255.17,0a255.17,255.17 0,1 1,510.35 0a255.17,255.17 0,1 1,-510.35 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#cacaca"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="m258.67,119.57q23.63,0 40.54,8.45 17.1,8.45 26.13,22.09 9.03,13.45 9.03,28.63 0,18.44 -6.92,30.16 -6.92,11.53 -17.29,19.6 -10.18,7.88 -20.56,15.56 -10.37,7.49 -17.48,17.68 -6.92,10.18 -6.92,26.13v13.26L232.73,301.13L232.73,285.95q0,-18.64 6.72,-30.93 6.92,-12.3 17.1,-20.94 10.18,-8.65 20.37,-15.95 10.18,-7.49 17.1,-16.14 6.92,-8.65 6.92,-21.33 0,-16.33 -13.06,-25.17 -13.06,-9.03 -32.47,-9.03 -13.64,0 -28.05,6.72 -14.41,6.53 -26.32,21.33l-23.06,-16.91q16.91,-19.79 37.08,-28.82 20.37,-9.22 43.61,-9.22zM249.83,341.29q11.14,0 18.64,7.49 7.49,7.49 7.49,18.06 0,10.76 -7.49,18.44 -7.49,7.49 -18.64,7.49 -10.76,0 -18.06,-7.49 -7.3,-7.69 -7.3,-18.44 0,-10.57 7.3,-18.06 7.3,-7.49 18.06,-7.49z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:drawable="@drawable/circle_guess"
|
||||
android:width="40dp"
|
||||
android:height="40dp"
|
||||
/>
|
||||
</layer-list>
|
@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512.35dp"
|
||||
android:height="512.35dp"
|
||||
android:viewportWidth="512.35"
|
||||
android:viewportHeight="512.35">
|
||||
<path
|
||||
android:pathData="M256.17,256.17m-255.17,0a255.17,255.17 0,1 1,510.35 0a255.17,255.17 0,1 1,-510.35 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#d0b7fb"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M171.42,85 L213.79,169.85 256.17,254.69 298.55,169.85 340.93,85L256.17,85ZM256.17,257.66 L213.79,342.5 171.42,427.34L256.17,427.34 340.93,427.34l-42.38,-84.84z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="6"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
</vector>
|
@ -0,0 +1,25 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512.35dp"
|
||||
android:height="512.35dp"
|
||||
android:viewportWidth="512.35"
|
||||
android:viewportHeight="512.35">
|
||||
<path
|
||||
android:pathData="M256.17,256.17m-255.17,0a255.17,255.17 0,1 1,510.35 0a255.17,255.17 0,1 1,-510.35 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#bafbb7"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="m159.28,190.03v227.07h65.16l0.41,-1.07L256.17,335.25l31.32,80.78 0.41,1.07h65.16L353.07,190.03Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="6.21387"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M256.17,192.14m-96.63,0a96.63,96.63 0,1 1,193.27 0a96.63,96.63 0,1 1,-193.27 0"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="6.73409"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
</vector>
|
@ -0,0 +1,16 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="512.35dp"
|
||||
android:height="512.35dp"
|
||||
android:viewportWidth="512.35"
|
||||
android:viewportHeight="512.35">
|
||||
<path
|
||||
android:pathData="M256.17,256.17m-255.17,0a255.17,255.17 0,1 1,510.35 0a255.17,255.17 0,1 1,-510.35 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#ff7f7f"
|
||||
android:strokeColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M325.85,129.86L255.11,200.6L185.43,130.92L140.95,175.39l69.68,69.68l-69.04,69.04l44.47,44.47l69.04,-69.04l70.1,70.1l44.47,-44.47l-70.1,-70.1l70.74,-70.75z"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
@ -0,0 +1,59 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="64"
|
||||
android:viewportHeight="64">
|
||||
<path
|
||||
android:pathData="M32,41L32,44"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M25.636,38.364L23.515,40.485"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M23,32L20,32"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M25.636,25.636L23.515,23.515"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M32,23L32,20"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M38.364,25.636L40.485,23.515"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M41,32L44,32"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M38.364,38.364L40.485,40.485"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffa500"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M32,32m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#ffa500"
|
||||
android:strokeColor="#ffa500"/>
|
||||
</vector>
|
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="33.104dp"
|
||||
android:height="24.037dp"
|
||||
android:viewportWidth="33.104"
|
||||
android:viewportHeight="24.037">
|
||||
<path
|
||||
android:pathData="M6.043,10.713A6,6 0,0 0,7.492 22.537L23.992,22.537a7.5,7.5 0,1 0,-1.755 -14.793l-2,0.543"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3"
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:strokeColor="?attr/colorControlNormal"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M22.237,7.744a8.25,8.25 0,0 0,-16.194 2.97,7.142 7.142,0 0,0 0.7,2.073"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3"
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:strokeColor="?attr/colorControlNormal"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="33dp"
|
||||
android:height="37.5dp"
|
||||
android:viewportWidth="33"
|
||||
android:viewportHeight="37.5">
|
||||
<path
|
||||
android:pathData="M15.558,1.165 L5.109,12.661a1.623,1.623 0,0 0,1.2 2.714L8.063,15.375L2.902,20.536A1.591,1.591 0,0 0,4.027 23.25L6.375,23.25L1.13,29.543A1.653,1.653 0,0 0,2.402 32.25L14.25,32.25v2.25a2.25,2.25 0,0 0,4.5 0L18.75,32.25L30.598,32.25a1.653,1.653 0,0 0,1.273 -2.707L26.625,23.25h2.348a1.591,1.591 0,0 0,1.125 -2.714l-5.161,-5.161h1.751A1.625,1.625 0,0 0,28.313 13.75a1.6,1.6 0,0 0,-0.422 -1.09L17.442,1.165a1.277,1.277 0,0 0,-1.884 0Z"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:strokeColor="?attr/colorControlNormal"/>
|
||||
</vector>
|
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="360.5dp"
|
||||
android:height="37.24dp"
|
||||
android:viewportWidth="360.5"
|
||||
android:viewportHeight="37.24">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M360.14,23.7h0ZM60.38,20.31c21.45,0 25.6,3.39 60.02,3.39 35.15,0 37.67,-3.39 60.02,-3.39 21.45,0 25.6,3.39 60.02,3.39 35.15,0 37.67,-3.39 60.02,-3.39 21.45,0 25.24,3.32 59.66,3.39L360.14,16.93c-21.45,0 -25.6,-3.39 -60.02,-3.39 -35.15,0 -37.67,3.39 -60.02,3.39 -21.45,0 -25.6,-3.39 -60.02,-3.39 -35.15,0 -37.67,3.39 -60.02,3.39 -21.45,0 -25.6,-3.39 -60.02,-3.39 -35.15,0 -37.67,3.39 -60.02,3.39L0,23.7c34.25,0 39.11,-3.39 60.38,-3.39ZM300.48,27.08c-35.15,0 -37.67,3.39 -60.02,3.39 -21.45,0 -25.6,-3.39 -60.02,-3.39 -35.15,0 -37.85,3.39 -60.2,3.39S95.35,27.09 60.2,27.09 22.35,30.47 0,30.47v6.77c35.15,0 38.03,-3.39 60.2,-3.39 22.35,0 24.88,3.39 60.02,3.39s37.85,-3.39 60.2,-3.39c21.45,0 25.6,3.39 60.02,3.39 34.97,0 37.67,-3.39 60.02,-3.39 21.45,0 25.6,3.39 60.02,3.39L360.49,30.47c-22.35,0 -24.88,-3.39 -60.02,-3.39ZM60.38,6.77c21.45,0 25.6,3.39 60.02,3.39 35.15,0 37.67,-3.39 60.02,-3.39 21.45,0 25.6,3.39 60.02,3.39 35.15,0 37.67,-3.39 60.02,-3.39 21.45,0 25.24,3.32 59.66,3.39L360.14,3.39c-21.45,0 -25.6,-3.39 -60.02,-3.39 -35.15,0 -37.67,3.39 -60.02,3.39 -21.45,0 -25.6,-3.39 -60.02,-3.39 -35.15,0 -37.67,3.39 -60.02,3.39 -21.45,0 -25.6,-3.39 -60.02,-3.39C24.88,0 22.35,3.39 0,3.39v6.77C34.25,10.16 39.11,6.77 60.38,6.77Z"/>
|
||||
</vector>
|
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="26.652dp"
|
||||
android:height="17.46dp"
|
||||
android:viewportWidth="26.652"
|
||||
android:viewportHeight="17.46">
|
||||
<path
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:pathData="M0,12.36A5.1,5.1 0,0 1,3.972 7.392a6.091,6.091 0,0 1,6 -4.8,5.942 5.942,0 0,1 3.792,1.308 5.88,5.88 0,0 1,2.16 3.36h0.324a5.1,5.1 0,0 1,5.112 5.088,5.121 5.121,0 0,1 -5.112,5.112L5.124,17.46a4.836,4.836 0,0 1,-1.98 -0.408,5.328 5.328,0 0,1 -1.644,-1.068 5.333,5.333 0,0 1,-1.092 -1.632,4.933 4.933,0 0,1 -0.408,-1.992ZM1.74,12.36a3.228,3.228 0,0 0,0.984 2.352,3.27 3.27,0 0,0 2.388,0.984L16.248,15.696a3.262,3.262 0,0 0,2.388 -0.984,3.212 3.212,0 0,0 1,-2.352 3.148,3.148 0,0 0,-1 -2.352,3.289 3.289,0 0,0 -2.388,-0.984L14.58,9.024a0.159,0.159 0,0 1,-0.18 -0.18l-0.084,-0.588a4.363,4.363 0,0 0,-4.368 -3.936,4.267 4.267,0 0,0 -2.952,1.128 4.169,4.169 0,0 0,-1.416 2.808l-0.084,0.5c0,0.12 -0.06,0.18 -0.192,0.18l-0.54,0.084A3.228,3.228 0,0 0,2.592 10.092a3.367,3.367 0,0 0,-0.852 2.268ZM12.36,1.896c-0.12,0.108 -0.1,0.192 0.084,0.252a10.7,10.7 0,0 1,1.3 0.66c0.132,0.036 0.228,0.024 0.264,-0.036a3.7,3.7 0,0 1,6.252 2.34l0.108,0.768h1.7a2.747,2.747 0,0 1,2.016 0.84,2.77 2.77,0 0,1 0.1,3.876 2.83,2.83 0,0 1,-1.836 0.924c-0.12,0 -0.18,0.06 -0.18,0.192v1.356c0,0.132 0.06,0.192 0.18,0.192a4.577,4.577 0,0 0,4.308 -4.548,4.589 4.589,0 0,0 -4.584,-4.584h-0.18a5.588,5.588 0,0 0,-5.34 -4.128,5.27 5.27,0 0,0 -4.188,1.9Z"/>
|
||||
</vector>
|
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="360dp"
|
||||
android:height="1dp"
|
||||
android:viewportWidth="360"
|
||||
android:viewportHeight="1">
|
||||
<path
|
||||
android:pathData="M0,0.5L360,0.5"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:strokeColor="#707070"/>
|
||||
</vector>
|
@ -0,0 +1,16 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="301.68dp"
|
||||
android:height="82.76dp"
|
||||
android:viewportWidth="301.68"
|
||||
android:viewportHeight="82.76">
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M10.3,0.5L291.38,0.5A9.8,9.8 0,0 1,301.18 10.3L301.18,72.46A9.8,9.8 0,0 1,291.38 82.26L10.3,82.26A9.8,9.8 0,0 1,0.5 72.46L0.5,10.3A9.8,9.8 0,0 1,10.3 0.5z"
|
||||
android:fillColor="#fff"
|
||||
android:strokeColor="#231f20"/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M33.55,41.38h174.32H33.55Z"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#231f20"/>
|
||||
</vector>
|
After Width: | Height: | Size: 944 KiB |
After Width: | Height: | Size: 416 KiB |
After Width: | Height: | Size: 671 KiB |
After Width: | Height: | Size: 889 KiB |
After Width: | Height: | Size: 375 KiB |
After Width: | Height: | Size: 146 KiB |
After Width: | Height: | Size: 126 KiB |
After Width: | Height: | Size: 450 KiB |
After Width: | Height: | Size: 866 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 986 KiB |
After Width: | Height: | Size: 744 KiB |
After Width: | Height: | Size: 961 KiB |
After Width: | Height: | Size: 557 KiB |
After Width: | Height: | Size: 1.7 MiB |
After Width: | Height: | Size: 493 KiB |
After Width: | Height: | Size: 176 KiB |
After Width: | Height: | Size: 164 KiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 312 KiB |
After Width: | Height: | Size: 365 KiB |
After Width: | Height: | Size: 594 KiB |
After Width: | Height: | Size: 635 KiB |
@ -0,0 +1,21 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M20.33,2a9.72,9.72 0,0 0,-6.12 2.17A5,5 0,0 0,6 7.59a7.08,7.08 0,0 0,-4 6.23v0.08H2v0a7,7 0,0 0,0.56 2.74,2.15 2.15,0 0,0 0.11,0.22A7.11,7.11 0,0 0,9.1 21H21.66a7.05,7.05 0,0 0,6 -3.32A9.38,9.38 0,0 0,30 11.5,9.6 9.6,0 0,0 20.33,2ZM11,5a3,3 0,0 1,1.8 0.6,9.58 9.58,0 0,0 -1.13,1.69 7.43,7.43 0,0 0,-2.48 -0.43,7.93 7.93,0 0,0 -1,0.07A3,3 0,0 1,11 5ZM26.11,16.42a0.71,0.71 0,0 0,-0.1 0.14A5.08,5.08 0,0 1,21.66 19H9.1a5.13,5.13 0,0 1,-4.62 -2.95l-0.05,-0.11 0,-0.1A4.74,4.74 0,0 1,4 14v-0.14a5.15,5.15 0,0 1,5.19 -5,5.27 5.27,0 0,1 2.52,0.64 1,1 0,0 0,0.83 0.05A1,1 0,0 0,13.13 9a7.68,7.68 0,0 1,7.2 -5A7.59,7.59 0,0 1,28 11.5,7.4 7.4,0 0,1 26.11,16.42Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M23.55,6.17a1,1 0,0 0,-1.1 1.66A4.59,4.59 0,0 1,24 12.76,1 1,0 0,0 24.76,14L25,14a1,1 0,0 0,1 -0.76A6.51,6.51 0,0 0,23.55 6.17Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M11,23a1,1 0,0 0,-1 1v5a1,1 0,0 0,2 0V24A1,1 0,0 0,11 23Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M16,23a1,1 0,0 0,-1 1v2.5a1,1 0,0 0,2 0V24A1,1 0,0 0,16 23Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M21,23a1,1 0,0 0,-1 1v3.75a1,1 0,0 0,2 0V24A1,1 0,0 0,21 23Z"/>
|
||||
</vector>
|
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="1920"
|
||||
android:viewportHeight="1920">
|
||||
<path
|
||||
android:pathData="m1739.3,1293.4 l-105.8,180.8 -240.2,-80.2 -24.5,22.3c-69.9,63.6 -150.2,109.7 -238.6,136.8l-32.1,9.9 -49.5,244.1L835.6,1807.1l-49.5,-244.2 -32.1,-9.9c-88.4,-27.1 -168.7,-73.2 -238.6,-136.8l-24.5,-22.3 -240.2,80.2 -105.8,-180.8 189.7,-164.4 -7.5,-33c-10.4,-45.7 -15.6,-91.5 -15.6,-135.9 0,-44.4 5.2,-90.1 15.6,-135.9l7.5,-33 -189.7,-164.4 105.8,-180.8 240.2,80.1 24.5,-22.3c69.9,-63.6 150.2,-109.7 238.6,-136.9l32.1,-9.8 49.5,-244.1h213l49.5,244.2 32.1,9.8c88.4,27.2 168.7,73.2 238.6,136.9l24.5,22.3 240.2,-80.2 105.8,180.8 -189.7,164.4 7.5,33c10.4,45.7 15.6,91.5 15.6,135.9 0,44.4 -5.2,90.1 -15.6,135.9l-7.5,33 189.7,164.6ZM1685.6,960c0,-41.8 -3.8,-84.5 -11.6,-127.3l210.2,-182.1 -199.5,-340.9 -265.2,88.4c-67,-55.6 -143.3,-99.4 -223.9,-128.4L1141,0L743.2,0l-54.7,269.7c-81.4,29.1 -156.4,72.3 -224,128.4L199.5,309.8 0,650.7l210.1,182.1c-7.7,42.8 -11.5,85.5 -11.5,127.3 0,41.8 3.8,84.5 11.5,127.2L0,1269.4 199.5,1610.2l265.2,-88.5c67,55.7 143.3,99.4 223.9,128.5l54.7,269.8h397.8l54.7,-269.7c81.3,-29.3 156.4,-72.3 223.9,-128.5l265.2,88.5 199.5,-340.9 -210.2,-182.2c7.8,-42.8 11.6,-85.5 11.6,-127.3ZM942.1,564.7C724.1,564.7 546.8,742 546.8,960c0,218 177.3,395.3 395.3,395.3 218,0 395.3,-177.3 395.3,-395.3 0,-218 -177.3,-395.3 -395.3,-395.3m0,677.6c-155.6,0 -282.4,-126.7 -282.4,-282.4s126.7,-282.4 282.4,-282.4S1224.4,804.4 1224.4,960s-126.7,282.4 -282.4,282.4"
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- No fill color -->
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
<!-- Border style -->
|
||||
<stroke android:width="1dp" android:color="#000000"/>
|
||||
</shape>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFF" /> <!-- Cell background color -->
|
||||
<stroke android:width="1dp" android:color="#000000" /> <!-- Border color and width -->
|
||||
</shape>
|
@ -0,0 +1,14 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M16,13.385C16,14.609 15.526,15.783 14.682,16.648C14.203,17.14 13.627,17.509 13,17.736M19,13.692C19,7.115 12,2 12,2C12,2 5,7.115 5,13.692C5,15.63 5.738,17.489 7.05,18.86C8.363,20.23 10.144,20.999 12,20.999C13.857,20.999 15.637,20.23 16.95,18.859C18.263,17.489 19,15.63 19,13.692Z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?attr/colorControlNormal"
|
||||
android:strokeLineCap="round"/>
|
||||
|
||||
</vector>
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="196.27dp"
|
||||
android:height="25.32dp"
|
||||
android:viewportWidth="196.27"
|
||||
android:viewportHeight="25.32">
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M10.3,0.5L185.97,0.5A9.8,9.8 0,0 1,195.77 10.3L195.77,15.02A9.8,9.8 0,0 1,185.97 24.82L10.3,24.82A9.8,9.8 0,0 1,0.5 15.02L0.5,10.3A9.8,9.8 0,0 1,10.3 0.5z"
|
||||
android:fillColor="?attr/colorControlNormal"
|
||||
android:strokeColor="?attr/colorControlNormal"/>
|
||||
</vector>
|
@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="800dp"
|
||||
android:height="800dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:pathData="M55.13,261.43c4.61,-4.72 9.61,-9.05 14.93,-12.96C54.27,232.77 44.49,211.05 44.49,187.03c0,-47.84 38.79,-86.63 86.63,-86.63c32.81,0 61.35,18.25 76.05,45.15c11.37,-7.76 23.87,-13.95 37.21,-18.3l0.64,-1.79c0.48,-1.32 0.34,-2.79 -0.35,-4c-0.71,-1.22 -1.91,-2.07 -3.29,-2.31l-32.66,-5.87c-1.96,-0.35 -3.5,-1.89 -3.86,-3.86l-5.87,-32.66c-0.25,-1.38 -1.09,-2.59 -2.31,-3.29c-1.21,-0.71 -2.67,-0.85 -4,-0.36l-31.22,11.21c-1.87,0.68 -3.97,0.12 -5.26,-1.4l-21.44,-25.33c-0.9,-1.07 -2.25,-1.69 -3.64,-1.69c-1.41,0 -2.74,0.62 -3.65,1.69L106.04,82.93c-1.29,1.53 -3.39,2.08 -5.27,1.42L69.55,73.13c-1.32,-0.48 -2.79,-0.35 -4.01,0.35c-1.22,0.7 -2.05,1.91 -2.31,3.29l-5.86,32.66c-0.36,1.97 -1.9,3.5 -3.86,3.86l-32.66,5.86c-1.39,0.25 -2.58,1.1 -3.29,2.31c-0.71,1.22 -0.84,2.68 -0.36,4.01l11.22,31.22c0.67,1.88 0.12,3.97 -1.41,5.27L1.69,183.39C0.62,184.29 0,185.63 0,187.03c0,1.41 0.62,2.74 1.69,3.65l25.33,21.44c1.53,1.29 2.08,3.39 1.41,5.27l-11.22,31.22c-0.48,1.33 -0.34,2.79 0.36,4.01c0.71,1.21 1.9,2.05 3.29,2.31l32.66,5.86C54.1,260.88 54.64,261.13 55.13,261.43z"
|
||||
android:fillColor="?attr/colorControlNormal"/>
|
||||
<path
|
||||
android:pathData="M483.62,290.7c-14.77,-14.78 -34.42,-24.74 -56.25,-27.51c-1.9,-34.17 -16.4,-65.07 -39.1,-87.75c-24.35,-24.37 -58.13,-39.49 -95.31,-39.48c-34.83,-0.01 -66.68,13.26 -90.57,34.97c-20.55,18.65 -35.28,43.64 -41.23,71.84c-5.78,-0.96 -11.69,-1.5 -17.73,-1.5c-29.62,-0.01 -56.55,12.03 -75.95,31.46c-19.42,19.39 -31.46,46.33 -31.46,75.94c0,29.62 12.04,56.56 31.46,75.95c19.4,19.42 46.33,31.46 75.95,31.46H415.12c26.72,0 51.01,-10.86 68.5,-28.38c17.51,-17.49 28.39,-41.79 28.38,-68.5C512.01,332.49 501.14,308.18 483.62,290.7zM465.75,409.83c-13,12.98 -30.82,20.97 -50.63,20.98H143.44c-22.72,-0.01 -43.18,-9.17 -58.08,-24.06c-14.89,-14.9 -24.05,-35.35 -24.06,-58.08c0.01,-22.72 9.17,-43.18 24.06,-58.08c14.9,-14.88 35.36,-24.05 58.08,-24.06c8.48,0 16.62,1.28 24.29,3.66l14.73,4.55l1.58,-15.34c2.82,-27.57 15.88,-52.09 35.34,-69.77c19.48,-17.66 45.22,-28.4 73.59,-28.4c30.27,0 57.58,12.23 77.44,32.08c19.85,19.85 32.07,47.16 32.08,77.44c0,1.07 -0.04,2.31 -0.1,3.77l-0.48,13.59l13.42,-0.52c19.73,0.07 37.47,8.04 50.43,20.97c12.98,13 20.96,30.82 20.98,50.63C486.71,379.02 478.73,396.84 465.75,409.83z"
|
||||
android:fillColor="?attr/colorControlNormal"/>
|
||||
</vector>
|
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="82.8dp" android:viewportHeight="82.76" android:viewportWidth="301.68" android:width="301.8258dp">
|
||||
|
||||
<path android:fillColor="#fff" android:pathData="M10.3,0.5L291.38,0.5A9.8,9.8 0,0 1,301.18 10.3L301.18,72.46A9.8,9.8 0,0 1,291.38 82.26L10.3,82.26A9.8,9.8 0,0 1,0.5 72.46L0.5,10.3A9.8,9.8 0,0 1,10.3 0.5z" android:strokeColor="#231f20" android:strokeWidth="1"/>
|
||||
|
||||
<path android:fillColor="#fff" android:pathData="M242.39,41.38m-20.27,0a20.27,20.27 0,1 1,40.54 0a20.27,20.27 0,1 1,-40.54 0" android:strokeColor="#231f20" android:strokeWidth="1"/>
|
||||
|
||||
<path android:fillColor="#00000000" android:pathData="M33.55,41.38h174.32H33.55Z" android:strokeColor="#231f20" android:strokeWidth="1"/>
|
||||
|
||||
</vector>
|
@ -0,0 +1,285 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".BoatRampActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/rampName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="Ramp Name"
|
||||
android:textColor="@color/textColor"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/rampImage"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="270dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rampName"
|
||||
app:srcCompat="@mipmap/ic_launcher" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rampImage">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/statusCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:cardBackgroundColor="#E9E9E9"
|
||||
app:cardCornerRadius="3000dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:layout_marginRight="3dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:fillViewport="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/statusText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#00FFFFFF"
|
||||
android:gravity="center"
|
||||
android:text="Unknown"
|
||||
android:textColor="@color/rampStatusText"
|
||||
android:textSize="24sp" />
|
||||
</HorizontalScrollView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/statusIcon"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
app:srcCompat="@drawable/circle_guess" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/openTimes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:cardCornerRadius="3000dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:layout_marginRight="3dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:fillViewport="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/openTimesText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:gravity="center"
|
||||
android:text="Unknown"
|
||||
android:textAlignment="gravity"
|
||||
android:textColor="@color/rampStatusText"
|
||||
android:textSize="24sp" />
|
||||
</HorizontalScrollView>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
app:srcCompat="@drawable/circle_hour_glass" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:cardCornerRadius="3000dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:layout_marginRight="3dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:fillViewport="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/addressText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:gravity="center"
|
||||
android:text="Unknown"
|
||||
android:textAlignment="gravity"
|
||||
android:textColor="@color/rampStatusText"
|
||||
android:textSize="24sp" />
|
||||
</HorizontalScrollView>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
app:srcCompat="@drawable/circle_copy" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/operator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:cardCornerRadius="3000dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:layout_marginRight="3dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:fillViewport="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/operatorText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:gravity="center"
|
||||
android:text="Unknown"
|
||||
android:textAlignment="gravity"
|
||||
android:textColor="@color/rampStatusText"
|
||||
android:textSize="24sp" />
|
||||
</HorizontalScrollView>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
app:srcCompat="@drawable/circle_ops" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/lastUpdated"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
app:cardCornerRadius="3000dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="3dp"
|
||||
android:layout_marginRight="3dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:fillViewport="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lastUpdatedText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:gravity="center"
|
||||
android:text="Unknown"
|
||||
android:textAlignment="gravity"
|
||||
android:textColor="@color/rampStatusText"
|
||||
android:textSize="24sp" />
|
||||
</HorizontalScrollView>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
app:srcCompat="@drawable/calendar" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,264 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:outlineProvider="none"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="LAKEWATCH"
|
||||
android:textSize="34sp"
|
||||
android:textStyle="bold|italic"
|
||||
android:textColor="@color/textColor"
|
||||
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.125" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="CANYON LAKE"
|
||||
android:textSize="34sp"
|
||||
android:textColor="@color/textColor"
|
||||
android:textStyle="bold|italic"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.177" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="45sp"
|
||||
android:layout_height="48sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.136"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.281"
|
||||
app:srcCompat="@drawable/icon_fa_solid_tree" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView2"
|
||||
android:layout_width="45sp"
|
||||
android:layout_height="48sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.89"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.281"
|
||||
app:srcCompat="@drawable/icon_fa_solid_tree" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView3"
|
||||
android:layout_width="400sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleY="2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.454"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.318"
|
||||
app:srcCompat="@drawable/line_1" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleX="1.1"
|
||||
android:scaleY="1.1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.49"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.981"
|
||||
app:srcCompat="@drawable/icon_material_sharp_water" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView5"
|
||||
android:layout_width="40sp"
|
||||
android:layout_height="45sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.706"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.023"
|
||||
app:srcCompat="@drawable/icon_akar_cloud" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView6"
|
||||
android:layout_width="40sp"
|
||||
android:layout_height="45sp"
|
||||
android:layout_marginBottom="220sp"
|
||||
android:rotationY="177"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.148"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.069"
|
||||
app:srcCompat="@drawable/icon_akar_cloud" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView7"
|
||||
android:layout_width="35sp"
|
||||
android:layout_height="45sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.252"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.018"
|
||||
app:srcCompat="@drawable/icon_weather_cloudy" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView8"
|
||||
android:layout_width="35sp"
|
||||
android:layout_height="45sp"
|
||||
android:rotationY="182"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.617"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.051"
|
||||
app:srcCompat="@drawable/icon_weather_cloudy" />
|
||||
|
||||
<Button
|
||||
style="@style/BaseButtonStyle"
|
||||
android:id="@+id/button"
|
||||
android:layout_width="200sp"
|
||||
android:layout_height="90sp"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="WEATHER"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.483"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.441"
|
||||
app:strokeColor="#000000"
|
||||
app:strokeWidth="7sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button2"
|
||||
android:layout_width="200sp"
|
||||
android:layout_height="90sp"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="WATER STATUS"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/button"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="@+id/button"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button"
|
||||
app:layout_constraintVertical_bias="0.019"
|
||||
app:strokeColor="#000000"
|
||||
app:strokeWidth="7sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button3"
|
||||
android:layout_width="200sp"
|
||||
android:layout_height="90sp"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="BOAT RAMPS"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
|
||||
app:layout_constraintEnd_toEndOf="@+id/button2"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="@+id/button2"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button2"
|
||||
app:layout_constraintVertical_bias="0.032"
|
||||
app:strokeColor="#000000"
|
||||
app:strokeWidth="7sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settingsButton"
|
||||
android:layout_width="200sp"
|
||||
android:layout_height="90sp"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="SETTINGS"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView4"
|
||||
app:layout_constraintEnd_toEndOf="@+id/button3"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="@+id/button3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button3"
|
||||
app:layout_constraintVertical_bias="0.049"
|
||||
app:strokeColor="#000000"
|
||||
app:strokeWidth="7sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView9"
|
||||
android:layout_width="75sp"
|
||||
android:layout_height="100sp"
|
||||
android:layout_marginTop="540dp"
|
||||
android:rotationY="177"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button3"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.235"
|
||||
app:layout_constraintStart_toEndOf="@+id/button3"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:srcCompat="@drawable/boat_ramp_svgrepo_com" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView11"
|
||||
android:layout_width="75sp"
|
||||
android:layout_height="100sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.922"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:srcCompat="@drawable/weather_symbol_4_svgrepo_com" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView12"
|
||||
android:layout_width="75sp"
|
||||
android:layout_height="100sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.922"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView11"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:srcCompat="@drawable/water_drop_svgrepo_com" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView14"
|
||||
android:layout_width="75sp"
|
||||
android:layout_height="100sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/settingsButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.235"
|
||||
app:layout_constraintStart_toEndOf="@+id/settingsButton"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:srcCompat="@drawable/settings_2_svgrepo_com" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainRampMenuActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/rampsOpen"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="\?/\? Ramps Open"
|
||||
android:textColor="@color/textColor"
|
||||
android:textSize="34sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/rampListingScrollView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rampsOpen"
|
||||
app:layout_constraintVertical_bias="0.0">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/rampListing"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,194 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".SettingsActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView3"
|
||||
android:layout_width="400sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleY="2"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.454"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.318"
|
||||
app:srcCompat="@drawable/line_1" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="45sp"
|
||||
android:layout_height="48sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.136"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.281"
|
||||
app:srcCompat="@drawable/icon_fa_solid_tree" />
|
||||
<ImageView
|
||||
android:id="@+id/imageView2"
|
||||
android:layout_width="45sp"
|
||||
android:layout_height="48sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.89"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.281"
|
||||
app:srcCompat="@drawable/icon_fa_solid_tree" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView6"
|
||||
android:layout_width="40sp"
|
||||
android:layout_height="45sp"
|
||||
android:layout_marginTop="52dp"
|
||||
android:rotationY="177"
|
||||
app:layout_constraintBottom_toTopOf="@+id/imageView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.11"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:srcCompat="@drawable/icon_akar_cloud" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView7"
|
||||
android:layout_width="35sp"
|
||||
android:layout_height="45sp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView6"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.252"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:srcCompat="@drawable/icon_weather_cloudy" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView8"
|
||||
android:layout_width="35sp"
|
||||
android:layout_height="45sp"
|
||||
android:rotationY="182"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/imageView6"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.651"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView5"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:srcCompat="@drawable/icon_weather_cloudy" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView5"
|
||||
android:layout_width="40sp"
|
||||
android:layout_height="45sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/imageView2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.77"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.08"
|
||||
app:srcCompat="@drawable/icon_akar_cloud" />
|
||||
|
||||
<Button
|
||||
style="@style/BaseButtonStyle"
|
||||
android:id="@+id/button5"
|
||||
android:layout_width="200sp"
|
||||
android:layout_height="90sp"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="DARK MODE"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/imageView3"
|
||||
app:layout_constraintVertical_bias="0.084"
|
||||
app:strokeColor="#000000"
|
||||
app:strokeWidth="7sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="SETTINGS"
|
||||
android:textSize="40sp"
|
||||
android:textStyle="bold|italic"
|
||||
android:textColor="@color/textColor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.422"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.155" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView14"
|
||||
android:layout_width="75sp"
|
||||
android:layout_height="100sp"
|
||||
android:layout_marginTop="112dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/imageView2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.88"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:srcCompat="@drawable/settings_2_svgrepo_com" />
|
||||
|
||||
<Button
|
||||
style="@style/BaseButtonStyle"
|
||||
android:id="@+id/button6"
|
||||
android:layout_width="200sp"
|
||||
android:layout_height="90sp"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="FORCE DATA FETCH"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button5"
|
||||
app:layout_constraintVertical_bias="0.047"
|
||||
app:strokeColor="#000000"
|
||||
app:strokeWidth="7sp" />
|
||||
|
||||
<Button
|
||||
style="@style/BaseButtonStyle"
|
||||
android:id="@+id/button7"
|
||||
android:layout_width="200sp"
|
||||
android:layout_height="90sp"
|
||||
android:fontFamily="sans-serif-black"
|
||||
android:text="CLEAR CACHE"
|
||||
android:textSize="25sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button6"
|
||||
app:layout_constraintVertical_bias="0.065"
|
||||
app:strokeColor="#000000"
|
||||
app:strokeWidth="7sp" />
|
||||
<ImageView
|
||||
android:id="@+id/imageView4"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleX="1.1"
|
||||
android:scaleY="1.1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.49"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.981"
|
||||
app:srcCompat="@drawable/icon_material_sharp_water" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,184 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".WaterLevelActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView10"
|
||||
android:layout_width="376dp"
|
||||
android:layout_height="251dp"
|
||||
android:layout_marginStart="21dp"
|
||||
android:layout_marginTop="341dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="182dp"
|
||||
android:background="#FFFFFF"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.726"
|
||||
app:srcCompat="@drawable/waterlevelgraph" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tableLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="1dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<TableRow>
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/table_border_with_lines"
|
||||
android:padding="8dp"
|
||||
android:text="Percent Full"
|
||||
android:textColor="@color/textColor" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/table_border_with_lines"
|
||||
android:padding="8dp"
|
||||
android:textColor="@color/textColor" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/table_border_with_lines"
|
||||
android:padding="8dp"
|
||||
android:text="Mean Water Level (ft)"
|
||||
android:textColor="@color/textColor" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/table_border_with_lines"
|
||||
android:padding="8dp"
|
||||
android:textColor="@color/textColor" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/table_border_with_lines"
|
||||
android:padding="8dp"
|
||||
android:text="Surface Area (acres)"
|
||||
android:textColor="@color/textColor" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/table_border_with_lines"
|
||||
android:padding="8dp"
|
||||
android:textColor="@color/textColor" />
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/your_text_view_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="92dp"
|
||||
android:layout_marginTop="300dp"
|
||||
android:layout_marginEnd="93dp"
|
||||
android:layout_marginBottom="399dp"
|
||||
android:text="Historical Water Data"
|
||||
android:textColor="@color/textColor"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cardView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="4dp"
|
||||
app:cardBackgroundColor="@android:color/white"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/waterLevelTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="WATER LEVEL"
|
||||
android:textSize="20sp"
|
||||
android:textColor="@color/textColor"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/waterLevelValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="36sp"
|
||||
android:textColor="@color/textColor"
|
||||
android:gravity="center"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/feetMsl"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Feet MSL"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/textColor"
|
||||
android:gravity="center"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dateTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/textColor"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/levelStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/textColor"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".WeatherActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/day_svg"
|
||||
android:layout_width="409dp"
|
||||
android:layout_height="212dp"
|
||||
android:src="@drawable/day"
|
||||
app:layout_constraintBottom_toTopOf="@id/weather_description"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.723" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/weather_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:textColor="@color/textColor"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/temperature"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/temperature"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="44dp"
|
||||
android:textColor="@color/textColor"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/wind_svg"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.498"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/wind_svg"
|
||||
android:layout_width="332dp"
|
||||
android:layout_height="110dp"
|
||||
android:src="@drawable/wind_svg"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.504"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.615" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="WIND"
|
||||
android:textColor="#000000"
|
||||
android:textSize="10dp"
|
||||
app:layout_constraintStart_toStartOf="@id/wind_svg"
|
||||
app:layout_constraintTop_toTopOf="@id/wind_svg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/wind_direction"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="216dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:gravity="center"
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintBottom_toBottomOf="@id/wind_svg"
|
||||
app:layout_constraintLeft_toLeftOf="@id/wind_svg"
|
||||
app:layout_constraintRight_toRightOf="@id/wind_svg"
|
||||
app:layout_constraintStart_toStartOf="@id/wind_svg"
|
||||
app:layout_constraintTop_toTopOf="@id/wind_svg"
|
||||
app:layout_constraintVertical_bias="0.494" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/wind_speed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="44dp"
|
||||
android:layout_marginTop="36dp"
|
||||
android:textColor="#000000"
|
||||
android:background="@android:color/transparent"
|
||||
app:layout_constraintStart_toStartOf="@id/wind_svg"
|
||||
app:layout_constraintTop_toTopOf="@id/wind_svg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/wind_gust"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="44dp"
|
||||
android:layout_marginBottom="36dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintBottom_toBottomOf="@id/wind_svg"
|
||||
app:layout_constraintStart_toStartOf="@id/wind_svg" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/precipitation_svg"
|
||||
android:layout_width="334dp"
|
||||
android:layout_height="119dp"
|
||||
android:src="@drawable/precipitation_svg"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.493"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/wind_svg"
|
||||
app:layout_constraintVertical_bias="0.104" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="49dp"
|
||||
android:layout_marginStart="240dp"
|
||||
android:layout_marginTop="36dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:src="@drawable/reshot_icon_weather_yrq52ezutw"
|
||||
app:layout_constraintStart_toStartOf="@id/precipitation_svg"
|
||||
app:layout_constraintTop_toTopOf="@id/precipitation_svg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chance_precipitation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintStart_toStartOf="@id/precipitation_svg"
|
||||
app:layout_constraintTop_toTopOf="@id/precipitation_svg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/amount_precipitation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintBottom_toBottomOf="@id/precipitation_svg"
|
||||
app:layout_constraintStart_toStartOf="@id/precipitation_svg" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView5"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:text="PRECIPITATION"
|
||||
android:textSize="10dp"
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintStart_toStartOf="@id/precipitation_svg"
|
||||
app:layout_constraintTop_toTopOf="@id/precipitation_svg" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/weather_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="weather.gov"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.498"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/precipitation_svg" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#00FFFFFF"
|
||||
android:backgroundTint="#949494"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/rampMenuCard"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="#E9E9E9"
|
||||
app:cardCornerRadius="30dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/statusIcon"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="150dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
app:srcCompat="@drawable/circle_guess" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/rampName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:text="Unknown Ramp"
|
||||
android:textAlignment="center"
|
||||
android:textColor="#7F7F7F"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:background="#7F7F7F" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#00FFFFFF"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/rampStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#00FFFFFF"
|
||||
android:text="Unknown Status"
|
||||
android:textAlignment="center"
|
||||
android:textColor="#7F7F7F"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 982 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 7.6 KiB |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#BB86FC</color>
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
<color name="colorAccent">#03DAC5</color>
|
||||
<color name="backgroundColor">#08446F</color>
|
||||
<color name="textColor">#FFFFFFFF</color>
|
||||
|
||||
<color name="buttonBackgroundColor">#9DCFED</color>
|
||||
<color name="rampInfoText">#515151</color>
|
||||
<color name="rampInfoBackground">#DAF0FD</color>
|
||||
<color name="buttonTextColor">#FFFFFFFF</color>
|
||||
<color name="rampStatusOpen">#C9FFD9</color>
|
||||
<color name="rampStatusClosed">#FFCBC9</color>
|
||||
<color name="rampStatusUnknown">#E9E9E9</color>
|
||||
</resources>
|
@ -0,0 +1,13 @@
|
||||
<resources>
|
||||
<style name="Theme.LakeWatch" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<!-- Other theme attributes -->
|
||||
<item name="android:background">@color/backgroundColor</item> <!-- Set background color here -->
|
||||
<item name="buttonStyle">@style/BaseButtonStyle</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="BaseButtonStyle" parent="Widget.AppCompat.Button">
|
||||
<item name="android:backgroundTint">@color/buttonBackgroundColor</item>
|
||||
<item name="android:textColor">@color/buttonTextColor</item>
|
||||
</style>
|
||||
</resources>
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary" >#6200EE</color>
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
<color name="colorAccent">#03DAC5</color>
|
||||
|
||||
<!-- Normal/Light mode -->
|
||||
<color name="backgroundColor">#ECF7FF</color>
|
||||
<color name="textColor">#000000</color>
|
||||
<color name="buttonBackgroundColor">#FFFFFF</color>
|
||||
<color name="buttonTextColor">#000000</color>
|
||||
<color name="rampInfoBackground">#FFFFFF</color>
|
||||
<color name="rampStatusText">#8D8D8D</color>
|
||||
<color name="rampInfoText">#8D8D8D</color>
|
||||
<color name="rampStatusOpen">#C9FFD9</color>
|
||||
<color name="rampStatusClosed">#FFCBC9</color>
|
||||
<color name="rampStatusUnknown">#E9E9E9</color>
|
||||
</resources>
|
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">LakeWatch</string>
|
||||
</resources>
|
@ -0,0 +1,12 @@
|
||||
<resources>
|
||||
<style name="Theme.LakeWatch" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- Other theme attributes -->
|
||||
<item name="android:background">@color/backgroundColor</item> <!-- Set background color here -->
|
||||
<item name="buttonStyle">@style/BaseButtonStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="BaseButtonStyle" parent="Widget.AppCompat.Button">
|
||||
<item name="android:backgroundTint">@color/buttonBackgroundColor</item>
|
||||
<item name="android:textColor">@color/buttonTextColor</item>
|
||||
</style>
|
||||
</resources>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
@ -0,0 +1,17 @@
|
||||
package edu.utsa.cs3443.lakewatch;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
5
Summer-2024/CS-3443/LakeWatch/LakeWatch/build.gradle.kts
Normal file
@ -0,0 +1,5 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
|
||||
}
|