This commit is contained in:
Ren Juan 2021-08-24 00:02:21 +00:00
parent e9f70bb9c2
commit 651793bfe2
9 changed files with 253 additions and 101 deletions

View File

@ -9,11 +9,9 @@ import useCachedResources from './hooks/useCachedResources';
import useColorScheme from './hooks/useColorScheme';
import Navigation from './navigation';
import { Trips } from './GT2';
import * as fs from 'fs';
export var debug:boolean = false;
var expoGeoState:any;
var debug:boolean = false;
var expoGeoState:any = null;
export default function App() {
const isLoadingComplete = useCachedResources();
@ -29,12 +27,11 @@ export default function App() {
if (status !== 'granted') {
setErrorMsg('Permission to access location was denied');
return;
}
} else Trips.setLocEnabled(true);
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
if (!errorMsg && location)
Trips.deltaLoc(JSON.stringify(location));
Trips.deltaLoc(location);
})();
}, []);

View File

@ -1,8 +1,19 @@
import * as React from 'react';
import React, { useState, useEffect } from 'react';
import * as Location from 'expo-location';
import { Coordinate } from "./Coordinate";
import { Text, View } from './components/Themed';
import { Alert, StyleSheet } from 'react-native';
import { useState, useEffect } from 'react';
import { Button, StyleSheet } from 'react-native';
var debug:boolean = false;
export var endPending:boolean = false;
var expoGeoState:any = null;
export var locEnabled:boolean = false;
const heartbeat:number = 500;
const displayBeat:number = 3;
export function getEndPending() { return(endPending) }
export function toggleEndPending() { endPending = !endPending;}
const styles = StyleSheet.create({
tripText: {
@ -14,68 +25,154 @@ const styles = StyleSheet.create({
fontWeight: 'bold',
}});
var lastLoc:any = null;
const heartbeat:number = 500;
const displayBeat:number = 3;
class Chronometer {
function Monitor() {
public display:string = "00.00.00";
clock:number = 0;
intervalID:any = null;
const [location, setLocation] = useState(Object);
const [errorMsg, setErrorMsg] = useState("");
useEffect(() => {
(async () => {
let { status } = await Location.requestBackgroundPermissionsAsync();
if (status !== 'granted') {
setErrorMsg('Permission to monitor location was denied');
return;
} else Trips.setLocEnabled(true);
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
Trips.deltaLoc(location);
})();
}, []);
expoGeoState = 'Waiting..';
if (errorMsg) {
expoGeoState = errorMsg;
} else if (location) {
expoGeoState = JSON.stringify(location);
}
}
class Trip {
public elapsed:string = "00.00.00";
ticks:number = 0;
interval:any;
segments:number = 1;
distance:number = 0;
ds:number = 0;
CO2:number = 0.0;
loc:Coordinate = new Coordinate(0.0,0.0);
startPoint:Coordinate = new Coordinate(0.0,0.0)
tick() {let hours:number = 0, minutes:number = 0, seconds:number = 0;
this.clock++;
hours = this.clock < 3600 ? 0 : (this.clock / 3600);
minutes = this.clock < 60 ? 0 : (this.clock - (hours * 3600)) / 60;
seconds = this.clock % 60;
this.display = hours + ":" + minutes + ":" + seconds;
this.ticks++;
hours = this.ticks < 3600 ? 0 : (this.ticks / 3600);
minutes = this.ticks < 60 ? 0 : (this.ticks - (hours * 3600)) / 60;
seconds = this.ticks % 60;
this.elapsed = hours.toFixed(0) + ":" + minutes.toFixed(0) + ":" + seconds.toFixed(0);
}
public start() { this.clock = 0;
this.intervalID = setInterval(this.tick, heartbeat);
public start() { this.interval = setInterval(() => this.tick(), heartbeat); }
public resume() { this.startPoint = new Coordinate(0.0,0.0)
this.loc = new Coordinate(0.0, 0.0);
this.segments++;
this.interval = setInterval(() => this.tick(), heartbeat); }
public stop() { this.ds = this.loc.distanceTo(this.startPoint);
this.distance += this.ds;
clearInterval(this.interval);
}
public resume() { this.intervalID = setInterval(this.tick, heartbeat); }
public stop() { clearInterval(this.intervalID); }
}
interface expoGeoObj {
coords: [
altitude:number,
altitudeAccuracy:number,
latitude:number,
accuracy:number,
longitude:number,
heading:number,
speed:number,
timestamp:number
]
}
export class GT2 {
loc:Coordinate = new Coordinate(0,0);
clock:Chronometer = new Chronometer();
startPoint:Coordinate = new Coordinate(0,0);
trip:Trip = new Trip();
endPoint:Coordinate = new Coordinate(0.0,0.0);
startPoint:Coordinate = new Coordinate(0.0,0.0);
displayInterval:number = displayBeat * heartbeat;
public distance:number = 0.0;
co2Rate:number = 0.0;
currTime:number = 0;
lastTime:number = 0;
co2Rate:number = 250.0;
z:number = 0.0;
public v:number = 0.0;
public inProgress:boolean = false;
public paused:boolean = false;
public elapsed:number = 0.0;
segments:number = 0;
elevation:number = 0.0;
public units:string = "km";
public CO2Effect:string = "carbon burden";
nTrips:number = 0;
parseGeoExpo(key:string, value:any) {}
n:number = 0.0;
m:number = 0.0;
public deltaLoc(lastFix:any) {
lastFix = JSON.stringify(lastFix);
let expoFix:expoGeoObj = JSON.parse(lastFix);
this.trip.loc.setLongitude(expoFix.coords['longitude']);
this.trip.loc.setLatitude(expoFix.coords['latitude']);
if (this.trip.startPoint.mLatitude == 0.0) {
this.trip.startPoint.mLatitude = this.trip.loc.mLatitude;
this.trip.startPoint.mLongitude = this.trip.loc.mLongitude;
}
this.trip.ds = this.trip.loc.distanceTo(this.trip.startPoint);
}
public end() {
this.trip.stop();
this.inProgress = false;
this.nTrips++;
toggleEndPending();
}
public setLocEnabled(value:boolean) { locEnabled = value}
public pause() {
if (!this.paused) {
this.trip.stop();
this.paused = true;
} else {
this.trip.resume();
this.paused = false;
}
}
public reset() {
this.startPoint = new Coordinate(0,0);
this.distance = 0.0;
this.co2Rate = 0.0;
this.currTime = 0;
this.lastTime = 0;
this.loc = new Coordinate(0,0);
this.endPoint = new Coordinate(0,0);
this.startPoint = new Coordinate(0,0);
this.v = 0;
this.inProgress = false;
this.paused = false;
@ -83,42 +180,40 @@ export class GT2 {
}
public end() {
this.clock.stop();
this.inProgress = false;
this.nTrips++;
}
public pause() {
if (!this.paused) {
this.clock.stop();
this.paused = true;
} else {
this.clock.start();
this.paused = false;
}
}
public start() {
this.reset();
this.clock.start();
this.trip = new Trip();
this.trip.start();
this.inProgress = true;
}
lt:number = 0.0;
public getTripSummary() : string {
return (
'Elapsed - ' + this.trip.elapsed + '\n' +
'Origin: ' + 'lat: ' + this.trip.loc.mLatitude.toFixed(8) +
' long: ' + this.trip.loc.mLongitude.toFixed(8) + '\n' +
'Destination: ' + 'lat: ' + this.trip.loc.mLatitude.toFixed(8) +
' long: ' + this.trip.loc.mLongitude.toFixed(8) + '\n' +
'CO2: ' + this.trip.CO2 + ' grams ' + this.CO2Effect );
}
public getTripPanel() : string {
if (this.inProgress)
if (this.inProgress) {
return (
'Elapsed - ' + this.clock.display + '\n' +
'Geo: ' + 'lat: ' + this.loc.mLatitude + ' long: ' + this.loc.mLatitude + '\n' +
'Vector: ' + 'distance: ' + this.distance + ' velocity: ' + this.v + '\n' +
'Elapsed - ' + this.trip.elapsed + '\n' +
'Geo: ' + 'lat: ' + this.trip.loc.mLatitude.toFixed(8) +
' long: ' + this.trip.loc.mLongitude.toFixed(8) + '\n' +
'Vector: ' + 'distance: ' + this.trip.ds + ' velocity: ' + this.v + '\n' +
'Altitude: ' + this.elevation + '\n');
else return("No trip in progress. " + this.nTrips + " trip(s) completed");
}
else return("No trip in progress. " + this.nTrips + " trip(s) completed.");
}
@ -149,12 +244,42 @@ export class TripDisplay extends React.Component {
render() {
if (!debug)
return(
<View>
<Text style={styles.tripText}>
{Trips.getTripPanel() }
</Text>
</View> );
else;
return(
<View>
<Text style={styles.tripText}>
{Trips.getTripPanel() }
</Text>
<Text>{expoGeoState}</Text>
</View> );
}
}
export class TripSummary extends React.Component {
constructor(props:any) {
super(props);
this.state = { slug: null };
}
render() {
return(
<View>
<Text style={styles.tripText}>
{Trips.getTripSummary() }
</Text>
</View> );
}
}

View File

@ -42,6 +42,7 @@ function RootNavigator() {
<Stack.Screen name="Root" component={BottomTabNavigator} options={{ headerShown: false }} />
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} />
<Stack.Group screenOptions={{ presentation: 'modal' }}>
<Stack.Screen name="Modal" component={ModalScreen} />
</Stack.Group>
</Stack.Navigator>
);
@ -51,7 +52,7 @@ function RootNavigator() {
* A bottom tab navigator displays tab buttons on the bottom of the display to switch screens.
* https://reactnavigation.org/docs/bottom-tab-navigator
*/
const BottomTab = createBottomTabNavigator<RootTabParamList>();
export const BottomTab = createBottomTabNavigator<RootTabParamList>();
function BottomTabNavigator() {
const colorScheme = useColorScheme();

View File

@ -5,7 +5,10 @@ import { ScreenInfo3 } from '../components/ScreenInfo';
const image = { uri: "https://meansofproduction.biz/images/GREENT.jpg" };
export default function HomeScreen() {
export var nav:any = null;
export default function HomeScreen(navigation:any) {
nav = navigation;
return (
<View style={styles.container}>
<ImageBackground source={image} resizeMode="cover" style={styles.image}>

View File

@ -4,6 +4,7 @@ import { Text, View } from '../components/Themed';
import { useState } from 'react';
import ScreenInfo from '../components/ScreenInfo';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Trips } from '../GT2';
export default function SettingsScreen() {
const [number, onChangeNumber] = React.useState("");
@ -26,15 +27,27 @@ export default function SettingsScreen() {
<View style={styles.controls} >
<Button
title="Jet"
onPress={() => Alert.alert('Jet Fuel Selected \n 285 g / passenger / km')}
onPress={() => {
Trips.co2Rate = 285.0;
Trips.CO2Effect = "carbon burden";
Alert.alert('Jet Fuel Selected \n 285 g / passenger / km')}
}
/>
<Button
title="Gasoline"
onPress={() => Alert.alert('Gasoline Selected \n 255 g for driver \n only passenger / km')}
onPress={() => {
Trips.co2Rate = 285.0;
Trips.CO2Effect = "carbon burden";
Alert.alert('Gasoline Selected \n 255 g for driver \n only passenger / km')}
}
/>
<Button
title="Food"
onPress={() => Alert.alert('Savings vs Gasoline Selected')}
onPress={() => {
Trips.co2Rate = -285.0;
Trips.CO2Effect = "carbon relief";
Alert.alert('Savings vs Gasoline Selected')}
}
/>
</View>
<TextInput
@ -42,7 +55,7 @@ export default function SettingsScreen() {
returnKeyType={'done'}
onChangeText={onChangeNumber}
value={number}
placeholder="250"
placeholder={Trips.co2Rate.toString()}
keyboardType="numeric"
/>
</View>

View File

@ -3,7 +3,8 @@ import { useState } from 'react';
import { Alert, Button, StyleSheet } from 'react-native';
import { Text, View } from '../components/Themed';
import { ScreenInfo2 } from '../components/ScreenInfo';
import { TripDisplay, Trips } from '../GT2';
import EndScreenInfo from '../components/EndScreenInfo';
import { locEnabled, getEndPending, toggleEndPending, TripDisplay, Trips } from '../GT2';
const styles = StyleSheet.create({
container: {
@ -30,8 +31,12 @@ const styles = StyleSheet.create({
function startTrip() {
if (!locEnabled ) {
Alert.alert("You must enable both foreground\n and background location tracking.");
return;
}
Trips.start();
Alert.alert('Trip Started');
}
@ -48,18 +53,14 @@ function pauseTrip() {
}
function endTrip() {
function endTrip() { Trips.end(); }
Trips.end();
Alert.alert('Trip Ended');
}
export default function TripScreen() {
export default function TripScreen( navigation:any ) {
const [sButtonText, setSButtonText] = useState("Start");
const [pButtonText, setPButtonText] = useState("Pause");
if (!getEndPending())
return (
<View style={styles.container}>
<Text style={styles.title}>Trip Control</Text>
@ -69,8 +70,8 @@ export default function TripScreen() {
<Button
title={sButtonText}
onPress={() => {
if (!Trips.inProgress) {setSButtonText("End");startTrip();}
else {setSButtonText('Start');setPButtonText('Pause');endTrip();}}
if (!Trips.inProgress) {setSButtonText("End");startTrip();setPButtonText('Pause');}
else {setSButtonText('Start');endTrip();}}
}
/>
<Button
@ -84,5 +85,17 @@ export default function TripScreen() {
<TripDisplay></TripDisplay>
</View>
);
else
return (
<View style={styles.container}>
<Text style={styles.title}>Trip Control</Text>
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
<EndScreenInfo path="/screens/TripScreen.tsx" />
<Button title={'Dismiss'}
onPress={() => { toggleEndPending(); if (getEndPending()) Alert.alert("t"); else Alert.alert("f"); }}
/>
</View>
);
}

View File

@ -4,7 +4,7 @@
## 2.0.0
- An Expo version of exactly the same functionality as the original 2011 app slightly enhanced
except it's a completed and x-platform app.
except it's a completed and x-platform app and the overall trip fuel consumption has been corrected.
This first replacement on play and first version on app store using an expo build will be maintained
but the binaries will be available [here](https://sameboat.live/sb-app) after 2.1 replaces it on the app stores.