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
|
||||||
|
|
||||||
|
}
|