firebase - 正确读取、使用 Firebase 数据以及使用 React Native 进行编写
问题描述
我正在尝试利用我的 Google Firebase 来保存设备详细信息、工作详细信息和工作订单等数据。我的想法是将它全部保存在firebase firestore上。在react-native中,我希望能够使用单独的函数文件来访问 firebase 上的数据,然后对其进行处理,然后在 firestore 上写入新信息。我在使用带有推送的异步函数临时将数据保存在数组中时遇到了一些麻烦,并且能够定期将该信息用于各种功能。下面的代码只会导致过多的promise异常。有没有更好的方法来编写脚本?或者,你有办法简化这个吗?
import firestore from '@react-native-firebase/firestore';
class Worker {
constructor(name, certifications, shift, location) {
this.name = name;
this.certifications = certifications;
this.shift = shift;
this.location = location;
this.currentPosition = location;
this.timeLeftinShift = 8;
this.schedule = [];
this.doneScheduling = false;
}
}
class WorkOrder {
constructor(
eID,
eType,
facility,
location,
priority,
timeStamp,
timeToComplete,
) {
this.eID = eID;
this.eType = eType;
this.facility = facility;
this.location = location;
this.priority = priority;
this.timeStamp = timeStamp;
this.timeToComplete = timeToComplete;
this.done = false;
}
}
class Facility {
constructor(name, location, maxOcc) {
this.name = name;
this.location = location;
this.maxOcc = maxOcc;
this.curOcc = 0;
}
}
//assigns a worker
export function assignWorker() {
var tempWorkers = [];
async function workers() {
const workersCollection = await firestore()
.collection('workers')
.get()
.then(async (querySnapshot) => {
querySnapshot.forEach(async (documentSnapshot) => {
let temp = new Worker(
documentSnapshot.id,
documentSnapshot.data().Certifications,
documentSnapshot.data().Shift,
[
documentSnapshot.data().Location.longitude,
documentSnapshot.data().Location.latitude,
],
);
tempWorkers.push(temp);
});
});
return tempWorkers;
}
var tempFacilities = [];
async function Facilities() {
var tempFacilities = [];
const facilitiesCollection = await firestore()
.collection('facility')
.get()
.then(async (querySnapshot) => {
querySnapshot.forEach(async (documentSnapshot) => {
let temp = new Facility(
documentSnapshot.id,
[
documentSnapshot.data().Location.longitude,
documentSnapshot.data().Location.latitude,
],
documentSnapshot.data()['Max Occupancy'],
);
tempFacilities.push(temp);
});
});
return tempFacilities;
}
var tempWorkOrders = [];
async function workOrders() {
var tempWorkOrders = [];
const workOrdersCollection = await firestore()
.collection('sample work order')
.get()
.then(async (querySnapshot) => {
querySnapshot.forEach(async (documentSnapshot) => {
let temp = new WorkOrder(
documentSnapshot.data()['Equipment ID'],
documentSnapshot.data()['Equipment Type'],
documentSnapshot.data().Facility,
getFCoord(documentSnapshot.data().Facility, tempFacilities),
documentSnapshot.data()['Priority(1-5)'],
documentSnapshot.data()['Submission Timestamp'],
documentSnapshot.data()['Time to Complete'],
);
tempWorkOrders.push(temp);
});
});
return tempWorkOrders;
}
// final part
console.log('Reached Assigned Schedule');
workOrders().then((y) => {
workers().then((z) => {
assignSchedule(z, y);
for (let i = 0; i < z.length; ++i) {
firestore()
.collection('schedules')
.doc(tempWorkers[i].name)
.set({
schedule: tempWorkers[i].schedule,
})
.then(() => {});
}
});
});
console.log('Reached Assigned Schedule');
function getFCoord(inFacility) {
Facilities().then((x) => {
for (let i = 0; i < x.length; ++i) {
if (inFacility === x[i].name) {
// //console.log(
// // 'fCoord lat: ',
// // x[i].location[0],
// // ', fCoord long: ',
// x[i].location[1],
// );
return [x[i].location[0], x[i].location[1]];
}
}
});
}
// if a task is completed, we remove the work order
// if a task isn't completed by shift end, we subtract the time spent on the task and change the work order to reflect that
// two points (long, lat) distance function
function distBetweenTwoGeoPoints(lat, long, lat2, long2) {
const earthRadius = 6371;
let deltaPhi = ((lat2 - lat) * Math.PI) / 180;
let deltaLambda = ((long2 - long) * Math.PI) / 180;
let phi1 = (lat * Math.PI) / 180;
let phi2 = (lat2 * Math.PI) / 180;
let a =
Math.sin(deltaPhi / 2) ** 2 +
Math.cos(phi1) * Math.cos(phi2) * Math.sin(deltaLambda / 2) ** 2;
let c = 2 * Math.atan(Math.sqrt(a), Math.sqrt(1 - a));
return earthRadius * c;
}
// initial schedule for the day will come from all work orders that haven't been completed before their shift
//based upon technician certification we'd filter the work orders applicable
// letiables for optimization
// probability of failure
// location distance
// priority
// function -> ()
//filter each task by worker which can complete them
//for each worker, filter tasks that they can complete
// urgency score will be function of priority and time since task has been requested
// real time will be time takes to complete + travel time
// multiplier will be a function of how long a task will take and how much time is left in that person's shift
function score(workorder) {
//return workorder.priority * timeSinceRequest(workorder.timeStamp);
return workorder.priority;
}
function listOfTasksPerWorker() {
workOrders().then((Workers) => {
workers().then((workorders) => {
let numWorkers = Workers.length;
let numTasks = workorders.length;
let possibleTasks = [];
for (let i = 0; i < numWorkers; ++i) {
let taskList = [];
for (let j = 0; j < numTasks; ++j) {
//console.log("equipment " + workorders[j].eType);
for (let k = 0; k < workers[i].certifications.length; ++k) {
//console.log("certif " + workers[i].certifications[k]);
if (workorders[j].eType === workers[i].certifications[k]) {
//check certifications
taskList.push(workorders[j]);
}
}
}
possibleTasks.push(taskList);
}
return possibleTasks;
});
});
}
//given task will be apart of taskList
function removeTask(task, taskList) {
let newArr = [];
for (let i = 0; i < taskList.length; ++i) {
if (task.eID === taskList[i].eID) {
newArr = taskList.slice(i, i + 1);
return newArr;
}
}
}
// while workers have shift
// go through workorders
// terminates either when all the workers shifts are full or when there are no work orders
function assignSchedule() {
workOrders().then((Workers) => {
workers().then((workorders) => {
let numDone = 0;
while (numDone < Workers.length && workorders.length > 0) {
console.log('before choose workers');
chooseWorkers(Workers, workorders);
console.log('pass choose workers');
for (let i = 0; i < Workers.length; ++i) {
if (Workers[i].timeLeftinShift <= 0) {
++numDone;
}
}
}
});
});
}
//change time left in workshift
//change location of worker
//say task is assigned, and remove from workorder IF COMPLETED
function assignTask(worker, workorder) {
workOrders().then((workorders) => {
let taskTime =
workorder.timeToComplete +
timeToGetFacility(worker.location, workorder.location);
if (worker.timeLeftinShift < taskTime) {
worker.timeLeftinShift = 0;
workorder.timeToComplete =
worker.timeToComplete - worker.timeLeftinShift;
} else {
worker.timeLeftinShift = worker.timeLeftinShift - taskTime;
workorder.timeToComplete = 0;
workorders = removeTask(workorder, workorders);
}
worker.location = workorder.location;
worker.schedule.push(workorder);
console.log('assign task');
});
}
function chooseWorkers() {
workOrders().then((Workers) => {
workers().then((workorders) => {
for (let i = 0; i < Workers.length; ++i) {
let keep = true;
let bestTaskw1;
let bestTaskw2;
let worker1Tasks = listOfTasksPerWorker(Workers, workorders)[i];
console.log('tasks: ', worker1Tasks);
let schedule = oneSchedule(Workers[i], worker1Tasks);
if (!schedule[0].length) {
break;
} else {
bestTaskw1 = schedule[0][0];
}
console.log('pass schedule');
if (!Workers[i].doneScheduling) {
for (let j = i + 1; j < Workers.length; ++j) {
if (!Workers[j].doneScheduling) {
let worker2Tasks = listOfTasksPerWorker(Workers, workorders)[j];
let schedule2 = oneSchedule(Workers[j], worker2Tasks);
if (!schedule2[0].length) {
break;
} else {
bestTaskw2 = schedule[0][0];
if (bestTaskw1.eID === bestTaskw2.eID) {
let w1SecondSchedule = oneSchedule(
Workers[i],
removeTask(bestTaskw1, worker1Tasks),
);
let w2SecondSchedule = oneSchedule(
Workers[j],
removeTask(bestTaskw1, worker1Tasks),
);
if (
bestTaskw1[1] - w1SecondSchedule[1] <
bestTaskw2[1] - w2SecondSchedule[1]
) {
keep = false;
i = i - 1;
//fix next line
worker1Tasks = removeTask(bestTaskw1, worker1Tasks);
break;
}
}
}
}
}
if (keep) {
assignTask(Workers[i], bestTaskw1, workorders);
}
}
}
});
});
}
function timeToGetFacility(point1, point2) {
const avgSpdKm = 70;
let timeToGetThere =
distBetweenTwoGeoPoints(point1[0], point1[1], point2[0], point2[1]) /
avgSpdKm;
return timeToGetThere;
}
function oneSchedule(worker1, worker1Tasks) {
let time1 = worker1.timeLeftinShift;
let total1 = 0;
let tasks1 = [];
let tempLocation = worker1.location;
while (time1 > 0) {
let bestOrder;
let bestOrderInd;
let bestScorePerHour = 0;
let travelTime = 0;
let bestTravelTime = 0;
console.log('before for');
console.log(worker1Tasks.length.toString());
for (let i = 0; i < worker1Tasks.length; ++i) {
console.log('before if');
console.log('test: ', i, worker1Tasks.length);
if (!worker1Tasks[i].done) {
console.log('after if');
let tempScorePerHour = 0;
console.log('location: ', tempLocation[0], tempLocation[1]);
travelTime = timeToGetFacility(
tempLocation,
worker1Tasks[i].location,
);
console.log('travel time: ', travelTime);
if (time1 - (worker1Tasks[i].timeToComplete + travelTime) < 0) {
tempScorePerHour =
(score(worker1Tasks[i]) *
((time1 - travelTime) / worker1Tasks[i].timeToComplete)) /
time1;
} else {
tempScorePerHour =
score(worker1Tasks[i]) /
(worker1Tasks[i].timeToComplete + travelTime);
}
console.log('score: ', score(worker1Tasks[i]));
console.log('temp: ', tempScorePerHour);
if (tempScorePerHour > bestScorePerHour) {
bestScorePerHour = tempScorePerHour;
bestOrder = worker1Tasks[i];
bestOrderInd = i;
bestTravelTime = travelTime;
}
}
}
if (bestScorePerHour > 0) {
worker1Tasks.splice(bestOrderInd, 1);
//bestOrder.done = true;
tasks1.push(bestOrder);
console.log(bestOrder.eID);
console.log(bestScorePerHour);
if (time1 - (bestOrder.timeToComplete + bestTravelTime) < 0) {
total1 += bestScorePerHour * time1;
time1 = 0;
} else {
total1 += score(bestOrder);
time1 -= bestOrder.timeToComplete + bestTravelTime;
}
console.log(bestOrder.timeToComplete);
tempLocation = bestOrder.location;
} else {
break;
}
}
return [tasks1, total1];
}
}
解决方案
推荐阅读
- ios - 如何分别使用 Alamofire 发送参数和正文?
- reactjs - 我需要将我的 Apollo 客户端缓存设置为默认值
- python - 如何使用比较语句在 python 中进行 REST 查询?
- ios - 在 Visual Studio App Center 中导入框架(使用 Carthage)时命令“CompileSwift normal arm64”失败
- mobile - 移动优先索引是否意味着以较低的分辨率开发?
- python - 在进程完成之前,Flask 多处理不会返回响应
- angular - Angular 4 过滤按钮点击
- web-services - 我们如何在 Hybris 6.7 的 oauth 响应中传递用户详细信息
- python - Python Urllib 下载视频但无法播放
- html - 如何在 onsenui navigator 中使用多个 html