You are on page 1of 252

Web-based Public Utility Vehicle and Passenger Queuing Management System

for Ormoc City Public Utility Vehicle Terminal:


A Proposed Passenger Assistance System with Mobile Application

A Capstone Project Proposal


Presented to the
Faculty of Bachelor of Science in Information Technology
Computer Studies Department
Eastern Visayas State University – Ormoc City Campus

In partial Fulfillment
of the Requirements for the Degree of
Bachelor of Science in Information Technology

by:
Caorte, Joelito Q.
Doyon, Jancarlo S.
Villas, John Carlo L.
.

Engr. Joseph Jaymel S. Morpos, MSIT


Capstone Project Adviser
January 2022

3
Acknowledgement

With deepest gratitude and appreciation, the researchers humbly give their gratitude to the
people who helped and supported to make this research study successful.

First praises to Almighty God, for giving the strength, knowledge, and motivation all
throughout and for the guidance that enabled us to surpass all the challenges the researchers have
encountered during the entire process of this research, and for the given passion to make this study
possible.

The researchers would like to express their sincere gratitude to the IT Head Department,
Engr. Joseph Jaymel Morpos for his immense knowledge, patience, guidance, comments, and support
for the accomplishment of this paper.

Research instructor Engr. Joseph Jaymel Morpos, thank you for the support, suggestions,
amendments, and encouragement to pursue this study, for helping us broaden our understanding and
improve our combined ideas in the pursuit for the betterment of the study.

To Engr. Edward B. Bertulfo for the time, suggestions and for helping to gather the necessary
information for the accomplishment of the study.

To Maria Queenna D. Mosquito for checking for any grammatical errors and improving the
terms for better precision of ideas and logic.

The completion of this project could also not have been achieved without the support of the
researcher’s friends who have offered some additional suggestions and thoughts about the study.

Lastly, to researcher’s supportive parents for their moral encouragement, financial assistance,
as well as the spiritual support that really empowered the researchers to put the study into completion.

The researchers would like as well to extend their deepest gratitude and genuine appreciation
to the Ormoc City Public Utility Vehicle Terminal Personnel for the cooperation, knowledge, and
patience they offered.

4
Abstract

The increase of establishments and services in Ormoc City together with the rise of
population leads to overcrowding in some major public utility infrastructures, because of this, public
transportations in the city are experiencing congestions, one of the affected areas is Ormoc City
Public Utility Vehicle Terminal where the study is focused, congestion in the terminal eliminates
proper queuing etiquette and promotes unfair behavior from passengers and Public Utility Vehicle
(PUV) drivers. Other existing related studies came up with the development of queuing management
systems, systems design and functions depends on the type of environment they are going to be
implemented. The researchers have yet to find existing system that is suitable for fast-paced
operations. To solve the problem faced by Ormoc City Public Terminal, the researchers developed a
queuing management system with mobile applications that can assist passengers and manage the
queue of PUVs and passengers. With the results of the system testing and the survey conducted by the
researchers, the researchers concluded that the system is a success and achieve its overall objectives
which is to manage and organize the queuing of PUVs and passengers. The system’s design and
approach can be a basis for future related studies as there are only few related existing systems that is
the same with the developed system.

5
Table of Contents

1.0 Capstone Project Description1


1.1 Overview of the Current State of Technology1
1.2 Project Objectives 2
1.2.1 General Objective2
1.2.2 Specific Objectives2
1.3 Scope and Limitations of the Project2
1.4 Significance of the Capstone Project2
2.0 Review of the Related Literature3
3.0 Conceptual Framework5
4.0 The Qrmoc – Passenger Queuing Assistance System6
4.1 System Overview6
4.2 System Objectives8
4.3 System Functions9
4.4 System Scope and Limitations31
4.5 Physical Environment and Resources33
4.6 Architectural Design35
5.0 Design and Implementation Issues41
6.0 Results and Observations45
7.0 Conclusion and Recommendations51
References53
Appendix A. Survey Questionnaire54
Appendix B. Hardware Requirements Specification55
Appendix C. Structured Chart56
Appendix D. Survey Documentation73
Appendix E. Test Case: Unit Testing81
Appendix F. Test Case: Integration Testing99
Appendix G. Resource Persons101
Appendix H. Personal Vitae102
Appendix I. System Source Code108
Appendix J. Grammarian’s Certificate244
Appendix K. Approval Sheet245

6
List of Tables

Table 6.0.31: System Testing45


Table 6.0.32: Acceptance Testing Frequency Distribution Table47
Table 6.0.33: Acceptance Testing Frequency Distribution Table 47
Table 6.0.34: Acceptance Testing Frequency Distribution Table 48
Table 6.0.35: Acceptance Testing Frequency Distribution Table 48
Table 6.0.36: Acceptance Testing Frequency Distribution Table 48
Table 6.0.37: Acceptance Testing Frequency Distribution Table 49
Table 6.0.38: Acceptance Testing Frequency Distribution Table 49
Table 6.0.39: Acceptance Testing Frequency Distribution Table 49
Table 6.0.40: Acceptance Testing Frequency Distribution Table 50
Table 6.0.41: Acceptance Testing Frequency Distribution Table 50
Table 6.0.42: Acceptance Testing Frequency Distribution Table 50
Appendix A. Survey Questionnaire54
Appendix B. Hardware Requirements Specification55
Appendix E. Table 6.0.1: Administrator Login Unit Testing 81
Appendix E. Table 6.0.2: Fresh Login Unit Testing81
Appendix E. Table 6.0.3: Reset Password (1) Unit Testing82
Appendix E. Table 6.0.4: Reset Password (2) Unit Testing82
Appendix E. Table 6.0.5: Security Questions Unit Testing82
Appendix E. Table 6.0.6: Administrator Dashboard Unit Testing83
Appendix E. Table 6.0.7: Edit Administrator Profile Unit Testing85
Appendix E. Table 6.0.8: Reset Default Password Unit Testing86
Appendix E. Table 6.0.9: Dispatcher Add & Change Duty Status Unit Testing86
Appendix E. Table 6.0.10: Register and Generate PUV QR Unit Testing87
Appendix E. Table 6.0.11: Queueing PUVs Unit Testing89
Appendix E. Table 6.0.12: Waiting Passengers Unit Testing89
Appendix E. Table 6.0.13: Returning PUVs Unit Testing90
Appendix E. Table 6.0.14: Dispatchers Profile Unit Testing90
Appendix E. Table 6.0.15: Edit Dispatcher Profile Unit Testing91
Appendix E. Table 6.0.16: Vehicles Profile Unit Testing 92
Appendix E. Table 6.0.17: Edit Vehicle Profile Unit Testing92
Appendix E. Table 6.0.18: Vehicle Passenger Logs Unit Testing93
Appendix E. Table 6.0.19: Login Unit Testing 94
Appendix E. Table 6.0.20: QR Code Scanner Unit Testing 94
7
Appendix E. Table 6.0.21: Queuing PUVs Unit Testing95
Appendix E. Table 6.0.22: Manual Queuing Unit Testing96
Appendix E. Table 6.0.23: Profile Unit Testing97
Appendix E. Table 6.0.24: QR Code Unit Testing97
Appendix E. Table 6.0.25: Queuing PUVs Unit Testing98
Appendix E. Table 6.0.26: Returning PUVs Unit Testing98
Appendix F. Table 6.0.27: Login, Registration, and Reset Password Integration Testing99
Appendix F. Table 6.0.28: Administrator Dashboard Integration Testing99
Appendix F. Table 6.0.29: Scan P UV and Passenger QR Code Integration Testing100
Appendix F. Table 6.0.30: Vehicle Profile and Dispatcher Profile Integration Testing100

List of Figures

Figure 3.1: Conceptual Framework Model 5


Figure 4.3.1: System Administrator’s Web Application Login page 9
Figure 4.3.2: System Administrator’s Web Application Sign-up page 10
Figure 4.3.3: System Administrator’s Web Application Security Questions page 11
Figure 4.3.4: System Administrator’s Web Application Reset Password page 11
Figure 4.3.5: System Administrator’s Web Application Toggle Settings menu 12
Figure 4.3.6: System Administrator’s Web Application Edit Username and Profile Photo 12
Figure 4.3.7: System Administrator’s Web Application Password Authentication 13
Figure 4.3.8: System Administrator’s Web Application Default Credentials 13
Figure 4.3.9: Add Dispatcher and Change Dispatcher’s Status 14
Figure 4.3.10: Register and Generate PUV QR Code 15
Figure 4.3.11: Queuing PUVs 16
Figure 4.3.12: Waiting Passengers 17
Figure 4.3.13: Returning PUVs 18
Figure 4.3.14: Dispatcher’s Profile 19
Figure 4.3.15: Edit Dispatcher’s Profile 19
Figure 4.3.16: Vehicles Profile 20
Figure 4.3.17: Editing Vehicle’s Profile 20
Figure 4.3.18: Vehicle Passenger Logs 21
Figure 4.3.19: Vehicle and Passenger Logs PDF Format 22
Figure 4.3.20: Dispatcher’s Application Log in 23
Figure 4.3.21: QR Code Scanner’s bottom navigation menu scanning a PUV QR Code 24
Figure 4.3.22: QR Code Scanner’s bottom navigation menu scanning a SafeOrmocV2 QR Code 24
Figure 4.3.23: Bottom sheet for setting destination and companion of the passenger 24
Figure 4.3.24: Bottom navigation menu scanner throwing an error for invalid QR Code25
8
Figure 4.3.25: Alert shown if passenger’s SafeOrmocV2 is not yet registered 25
Figure 4.3.26: Bottom sheet for registering unregistered passengers SafeOrmocV2 QR Code 25
Figure 4.3.27: List of Queuing PUVs 26
Figure 4.3.28: PUV information and onboard passengers 26
Figure 4.3.29: Manual Queuing 27
Figure 4.3.30: Profile Screen 28
Figure 4.3.31: QRs interface 29
Figure 4.3.32: Using the camera to register and scan SafeOrmocV2 QR Code 29
Figure 4.3.33: Choosing QR image to be scan and register with the help of image gallery application
29
Figure 4.3.34: Queuing PUVs 30
Figure 4.3.35: Returning PUVs 31
Figure 4.6.1: System Architecture 35
Figure 4.6.2: Administrator’s Data Flow Diagram 37
Figure 4.6.3: Dispatcher’s Data Flow Diagram 38
Figure 4.6.4: Passenger’s Data Flow Diagram 39
Figure 4.6.5: Structured Chart – Database Schema40
Appendix C. Structured Chart - Administrator 56
Appendix C. Structured Chart – Administrator (Register PUV) 57
Appendix C. Structured Chart – Administrator (Queuing PUVs) 58
Appendix C. Structured Chart – Administrator (Waiting Passengers) 59
Appendix C. Structured Chart – Administrator (Returning PUVs) 60
Appendix C. Structured Chart – Administrator (Add & Manage Dispatcher PUVs) 61
Appendix C. Structured Chart – Administrator (Report Logs) 62
Appendix C. Structured Chart – Administrator (Dispatcher Profiles) 63
Appendix C. Structured Chart – Administrator (Vehicle Profiles) 64
Appendix C. Structured Chart – Dispatcher (Login) 65
Appendix C. Structured Chart – Dispatcher (QR Code Scanner) 66
Appendix C. Structured Chart – Dispatcher (Queuing PUVs) 67
Appendix C. Structured Chart – Dispatcher (Manual Queuing) 68
Appendix C. Structured Chart – Dispatcher (Profile) 68
Appendix C. Structured Chart – Passenger 69
Appendix C. Structured Chart – Passenger (View QR Code) 70
Appendix C. Structured Chart – Passenger (Queuing PUVs) 71
Appendix C. Structured Chart – Passenger (Returning PUVs) 72
Appendix D. Survey Documentation – Bus, Van, and Multicab at day73
Appendix D. Survey Documentation – Bus, Van, and Multicab at night73
9
Appendix D. Survey Documentation – Proponents setting up administrator web page74
Appendix D. Survey Documentation – Administrator interacting with the application74
Appendix D. Survey Documentation – Front view of the ticketing booth75
Appendix D. Survey Documentation – Queuing multicabs75
Appendix D. Survey Documentation – Ormoc City Public Utility Vehicle Terminal without queuing g
PUVs76
Appendix D. Survey Documentation – Queuing passengers76
Appendix D. Survey Documentation – Proponents explaining how the application works77
Appendix D. Survey Documentation – Dispatcher interacting with the dispatcher mobile
application77
Appendix D. Survey Documentation – Other dispatchers interacting with the dispatcher mobile
application78
Appendix D. Survey Documentation – Dispatcher interacts with the QR code scanner78
Appendix D. Survey Documentation – Dispatcher’s interaction with the dispatcher mobile
application79
Appendix D. Survey Documentation – Passenger registering SafeOrmocV2 QR code79
Appendix D. Survey Documentation – Passenger interacting with the mobile application80
Appendix I. System Source Code – Log in108
Appendix I. System Source Code – Sign up112
Appendix I. System Source Code – Sign up security questions114
Appendix I. System Source Code – Reset password’s security questions119
Appendix I. System Source Code – Password reset123
Appendix I. System Source Code – Editing administrator’s username and profile photo126
Appendix I. System Source Code – Resetting administrator’s web-based application131
Appendix I. System Source Code – Log out133
Appendix I. System Source Code – Adding dispatcher and setting dispatcher status134
Appendix I. System Source Code – Register and generate PUV QR145
Appendix I. System Source Code – Queuing PUVs164
Appendix I. System Source Code – Waiting passengers170
Appendix I. System Source Code – Returning PUVs172
Appendix I. System Source Code – Dispatcher profile177
Appendix I. System Source Code – Vehicle profile185
Appendix I. System Source Code – Vehicle and passenger logs195
Appendix I. System Source Code – Log in202
Appendix I. System Source Code – QR code scanner207
Appendix I. System Source Code – PUV list 219
Appendix I. System Source Code – Passenger list223
Appendix I. System Source Code – Manual queuing226
10
Appendix I. System Source Code – Dispatcher’s profile228
Appendix I. System Source Code – Passenger’s QR code list229
Appendix I. System Source Code – Registering QR code using mobile phone’s camera232
Appendix I. System Source Code – Registering passenger’s QR code using react-native-picker and
image gallery238
Appendix I. System Source Code – Queuing PUV list239
Appendix I. System Source Code – Returning PUV list241

11
1.0 Capstone Project Description

1.1 Overview of the Current State of Technology/Background of the Study

Transportation systems are an integral aspect of our world's larger technological, social, and
environmental systems. Most of the people, especially those common ones, use public utility vehicles
on a daily basis to go to their desired destinations, such as to school, workplace, or to go on a
vacation. Without transportation, the economy would collapse in an instant. A good Passenger
Queuing System is very important to be considered for every public terminal to manage the crowd
and promote fairness by prioritizing those passengers who are already on the queue.

“Queuing which always takes place in the form of lining up, is rarely anyone’s favorite
activity. It is a cornerstone for measurement of efficiency and organizational capability for most
service industries particularly in the airline industry. This feature has become a regular and recurrent
problem at Nnamdi Azikiwe International Airport (NAIA) which is the main and only airport that
services Nigerian capital city, Abuja with both domestic and international terminal”. (Ademoh, A,
Anosike, & Nneka, E, 2014). Multi Server approach of modelling was applied to develop a
mathematical model to solve problem of queuing of air transport passengers at NAIA in Abuja,
Nigeria’s capital city. (Ademoh, A, Anosike, & Nneka, E, 2014).

Cebu Pacific utilizes a cloud-based Queue Management System (QMS), which gives the
ability to see the real-time length of customers’ waiting times, allowing manpower and prioritization
of services where there is high demand (Press release, 2018). In the study conducted by Navarro,
Maricar, Bano, Rose Marie Lou, et al. (2015), they studied the long queues of trucks and ships to
identify the optimal number of berths and truck gates to create a faster movement of containers inside
and outside the port. The result shows an optimal number of six berths with 86% utilization that was
validated using Pro Model Software. It proves that the current number of berths was optimal and can
still accommodate the current quantity of inflow and outflow of containers. By that, they recommend
a booking system for truck arrivals for early planning of container pickups on which dedicated servers
will be allocated to accommodate booked trucks.

An intelligent transportation system (ITS) is an elaborate application that aims to provide


innovative services related to specific modes of transportation and traffic management, allowing users
to be better informed and use transportation networks in a safer, more coordinated, and "smarter"
manner.

The Ormoc City Public Utility Vehicle Terminal uses manual listing of PUVs queuing, but
the traditional way of recording the data possesses some disadvantages. The data could be lost due to
human error, could create biased way of assessing the queuing due to some personal agendas. For that
reason, those might create more conflicts that result to unorganized and inefficient passenger queuing.

Considering the fact that Ormoc City is a growing City in Eastern Visayas, relevant dilemmas
may arise with regards to a growing number of public utility vehicles and passengers as well, such as
heavy traffic and unorganized queuing for both PUVs and passengers. We can see this kind of
situation in Ormoc City Public Terminal where organized queuing is vaguely observed and yields to
some complications, such as competing to get in first to avoid delays, quarrels and among others. The
web based PUV and passenger queuing management system with mobile application for passenger

1
assistance is a system that helps resolve the problem faced by Ormoc City Public Utility Vehicle
Terminal.

1.2 Capstone Project Objectives

1.2.1 General objectives

To develop a PUV and passenger queuing management system in Ormoc City Public Utility
Vehicle Terminal.

1.2.2 Specific Objectives

The study specifically aims:

● To study the current situation regarding PUV and passenger queue in Ormoc City Public
Utility Vehicle Terminal.
● To determine what could be enhanced on the current situation on PUV and passenger queue
in the Ormoc City Public Utility Vehicle Terminal.
● To formulate an alternative method that will enhance the management of PUV and passenger
queue in Ormoc City Public Utility Vehicle Terminal.
● To determine what current technologies can be included in the enhancement of the current
situation on PUV and passenger queue in Ormoc City Public Utility Vehicle Terminal.
● To study the technologies that will be used in the enhancement of the current situation on
PUV and passenger queue in Ormoc City Public Utility Vehicle Terminal.
● To integrate current technologies and replace some of the traditional method used on the
management of PUV and passenger queue in Ormoc City Public Utility Vehicle Terminal.

1.3 Scope and Limitations of the Project                                      

This study only focuses on public utility vehicles located in Ormoc City. The public utility
vehicles in Ormoc City consist of Van, Bus, and Multicab, yet the study is solely designed to cater
Multicabs that routes from Albuera-Ormoc, Valencia-Ormoc, Sabang-Bao-Ormoc, Puertobello-
Ormoc. The center of the study is to develop a system that provides a Passenger Assistance System in
Ormoc City Public Utility Vehicle Terminal. The features of the system that is to be developed are
queuing management for both PUV and passenger and displays the number of passengers and
vehicles currently queuing in Ormoc City terminal. Tracking for the PUV destination, mobile
application for drivers, and other routes of transportation are not included in the study.

1.4 Significance of the Capstone Project

         As a growing City it is necessary to develop a queuing system of PUV terminal to provide
smooth queuing system. To regulate effectively and efficiently the queuing system, the passenger
assistance system will help to reduce complications with regards to determining the number of both
PUVs coming back to terminal and the number of passengers currently queuing in a specific route.
The researchers want to give emphasis to the people that Information Technology is inevitably part
2
and means of our evolving and growing society; this becomes somehow vital as commodities. In
addition to that, through this system people will realize that Information Technology really helps in
solving relevant concerns through developing system that offers relief and convenience.

2.0 Review of Related Literature

Developing something that will provide solutions to the act of queuing and waiting for a
service is important nowadays due to the increasing population of people and since mobile application
can already be found and are used everywhere, it would be a better idea to use mobile phones in
developing a queuing management system (Ghazal, Hamouda, & Ali, 2015). Other fields that have
felt the challenge of queuing are healthcare systems, queuing is a challenge for all healthcare systems
in the developed world and that research has been done on improving it (Seun Bature, Jahun, Nasir,
Hassan, & Toro, 2019). Queuing and waiting for services have been part of human activities and this
is because there is a lot of people to serve and the service provided is less (Seun, et al., 2019). The
same with the Ormoc City Public Utility Vehicle Terminal, during rush hours the passengers will just
accumulate the area resulting to overcrowding that will contribute to conflict between passengers
because there were a lot who are wanting to be served but the service is not well managed and is not
adapted to the magnitude of service that it should serve.

Mobile phone is ideal in developing a Queuing Management System because it is already


widely used and can be found everywhere (Ghazal, et.al., 2015). Mobile application changes the way
people use mobile phones (Butler, 2010). The proponent’s system will also develop mobile phones
applications, specifically android smart phones applications that will be used by passengers and
dispatchers. There were only two dominant smart phones operating system in the market namely,
android and IOS, but android platform surely has more users than IOS because it can be found on
budget friendly devices and brands unlike IOS that is only found in Apple devices with higher price.
Android and iPhones are the conqueror in the consumer market, and users are getting use of these
devices and are comfortable on using them in work (Jain & Sharma, 2013). Android is increasing in
share percentage in the market (Jain & Sharma, 2013). The increasing share percentage of android
might also be the reason on why android applications had grown exponentially and achieve great
success (Guerrouj & Baysal, 2016). With the strict rules and requirements that are necessary in
developing iPhones IOS applications that the proponents lack and cannot afford, the proponents
decided to only focus developing the application for android platform. Future project proponents can
consider developing application for IOS to fully provide application to all users.

In Ormoc City Public Utility Vehicle Terminal, time is greatly important, passengers must be
loaded to PUV as soon as possible and PUV drivers are racing on getting back to queue again. The
proponents must design the system to be fast and quick responsive, with that said, the proponents use
Quick Response (QR) code that stores the encrypted information of PUVs, for the passengers, the
existing SafeOrmocV2 QR code will be used to determine the identity of the passenger. QR codes are
the entrance to Internet of Things (IoT), this is because of the growing number of uses on smart
phones or mobile devices and its capability to store information and retrieving it easy and fast
(Ramalho, Correia, Fu, António, Brites, André, & Carlos, 2019). Another study that uses QR code for
flexibility in storing and reading information is a smart bus tracking system based on location-aware
services and QR codes with the use of GPS, GSM, QR coding and Google’s map technologies (Eken
& Sayar, 2014). this is greatly similar with the proponent’s study, one of the main focus of the
proponents study also is to let passengers use their time efficiently by providing real time update of
PUVs’ status.

3
The application of agent technology has seen to have the potential to improve the
performance of traffic and transportation system (Chen & Cheng, 2010). It is important to use the
present tools that can provide semi-automation and improvements in the current state of major public
utilities like terminals, in the case of Ormoc City Public Utility Vehicle Terminal, it is clearly seen
that the personnel are having trouble handling the number of passengers that depends on the terminal
in their commute. It is reasonable for the Ormoc City Public Utility Vehicle Terminal to have some
upgrade, in fact, all PUV terminal in the Philippines should be modernized and must be equipped with
technology that can provide efficiency and improve the performance of the transportation system. At
this time, many have witnessed how ride hailing services have changed the overall transportation
system, ideas such like this should not be constrained but also be applied to the public transportation
services, it could be applied experimentally for observation and further adjustment. The government
should consider upgrade on transportation facilities and should look at the increasing population of
the Philippines, will the existing transportation system that is used today be able to accommodate all
the Filipinos in the future. Dowd, Franz, & Wasek, (2018) states that “System availability for aging
transportation infrastructure decreases in the absence of maintenance and modernization activities.”
(p. 1).

The proponents’ aims to modernize and replace those replaceable traditional manual methods
in boarding of passengers and queuing of both PUVs and passengers in Ormoc City Public Utility
Vehicle Terminal with electronic computing devices that is extremely familiar to the terminal
personnel and passengers. The proponents believe that electronic computing devices will provide an
easier and more efficient way of managing the daily routines in Ormoc City Public Utility Vehicle
Terminal. Computer applications have seen to be important in every aspect of human activity
(Cosmas, Etus, Ajere, & Godswill, 2015). Technology is the way in making life easier and
comfortable when talking about service (Mahzabeen, 2019). The same with what the proponents think
would bring comfort to the people involved in Ormoc City Public Utility Vehicle Terminal’s daily
operation.

4
3.0 Conceptual Framework

ORMOC CITY PUBLIC UTILITY VEHICLE TERMINAL

PROBLEM SOLUTION

Queuing management system with


Unorganized queuing of
mobile passenger assistance
passengers and PUVs
application

PLANNING

DEVELOPMENT Features/Functions/
Capabilities

Hardware

TESTING

UNIT TESTING INTEGRATION TESTING SYSTEM TESTING

END-USERS COMMENTS/RECOMMENDATIONS

System’s defense panel DEPLOYMENT

Ormoc City Public Utility Vehicle Terminal


passengers

Figure 3.1 Conceptual Framework Model

The model represents the concepts used in developing the project. The source of the problem
is Ormoc City Public Utility Vehicle Terminal’s unorganized queuing of PUVs and passengers, the
solution formulated by the proponents is to develop a queuing management system with mobile
passenger assistance application. System planning is where the system’s appropriate hardware,
software, and features are determined. System development will then be the priority of the proponents
after the system planning, in here the system’s features are made using the software and hardware that
was chosen during system planning. After development, testing will be done to the system, this
includes unit testing which tests the independent units or modules, integration testing which test the
integrated units or modules, and lastly is the system testing which tests the overall system with each
unit or modules integrated and forms the system. If during testing the proponents does not find any
problem or bugs from the system then it is clear to deploy the system in Ormoc City Public Utility
Vehicle Terminal, during deployment, the proponents will carry out a survey to know the user’s
feedback/comments about the system, users feedback/comments will be analyzed by the proponents to
5
make adjustments to the system. The recommendations of the panel to the system during system’s
defense are the most accurate because the panels perform a thorough investigation of the system and
because of that the proponents prioritize those recommendations to be put into the system. The
proponents use incremental development approach in developing the system, it is clearly seen in the
conceptual framework that the system development relies on its users feedback to create some
adjustment and additional functionalities to the system.

4.0 The Qrmoc – Passenger Queuing Assistance System

The following are the overall specification and functional requirements of the software to be
developed:

● Manages the queuing of PUV and passengers using the mobile application dedicated for
dispatchers.
● Evenly and fairly assign each passenger to the queuing PUVs based on which PUV queue
first.
● Identifies passengers using the SafeOrmocV2 QR code.
● Uses the PUV plate number as a way for distinguishing which PUV the passenger boarded
and which PUV is assigned to the passenger
● Generate logs or reports of every PUV that departed from Ormoc City Public Utility Vehicle
Terminal.
● Manual queue which doesn’t requires SafeOrmocV2, the system must not interfere or put
burden for the passengers, it must allow passengers with no SafeOrmocV2 QR code in hand
to still board a PUV.
● Let passengers register their SafeOrmocV2 QR code in the system and view currently
queuing and returning PUVs using the dedicated mobile application for passengers.
● Manage the system’s task using the web-based application dedicated for the system’s
administrator.
● Uses network connection (internet) to disseminate data to involved parties.

With all these functionalities that the system will deliver, it is expected that the system will
provide convenience and relief for the Ormoc City Public Utility Vehicle Terminal personnel and for
the Ormoc City commuters.

4.1 System Overview

The following are the system’s main feature and capabilities:

Reads and validate QR codes

Using the dispatcher’s mobile application that can scan QR codes, the system will be able to
read and validate the content encoded in the QR code if the QR code is valid (SafeOrmocV2 QR code
and QR code generated by the system for registered PUV) or not.

Automated PUV assignment to passengers

Scanning the SafeOrmocV2 QR code of a passenger using the dispatcher mobile application
QR code scanner will allow the system to validate if the passenger has already boarded a PUV and
assign automatically an available PUV that can be boarded if not. Available PUVs are determined by
6
the system based on the numbers of onboard passengers (full or not full) and status (queuing or
departed) of the PUV. PUV plate number is used to identify what PUV the passenger will be
boarding.

Passengers’ manual queuing and boarding to PUV

The system allows passengers with no SafeOrmocV2 QR code to board a PUV by manually
entering the required information to queue and board a PUV.

Automatically generates log of every PUV that departed

The system is capable of generating logs of every PUV that departed from Ormoc City Public
Utility Vehicle Terminal. The log contains the name of the driver and operator of the PUV, time the
PUV queued, time the PUV departed, count of onboard passengers, time the log is generated, and list
of names of onboard passengers as well as the indication if a passenger has a companion when
boarded the PUV.

Generates encrypted QR codes for registered PUVs

The system is capable of generating QR codes for registered PUV that has encrypted encoded
content that can only be decrypted by the system itself.

Keeps track of the count of waiting passengers

Passengers with no available PUV going to their destination are automatically listed by the
system in waiting passengers list, the system counts the waiting passengers and reports the count to
the system’s administrator.

Sets PUV state to queuing or returning

The system can set the state of PUVs to queuing and returning. Using the dispatcher’s mobile
application that can scan QR codes, a PUV can be set to queuing mode by scanning the QR code of
the PUV and validating the current state of the PUV. PUV state can be set to returning mode through
the system administrator’s judgment and decision based on the transaction between the system
administrator and PUV driver or operator.

Keeps track of returning and queuing PUVs

The system keeps a record of queuing and returning PUVs for a moment, these records can be
viewed by the passengers.

Stores information securely

The system stores securely in a database every passenger, dispatcher, PUV, and
administrator’s information.

Shows queuing PUVs to dispatchers

With the use of the dispatchers’ mobile application, dispatchers can view and dequeue PUVs
for any good reasons.

Shows onboard passengers to dispatchers

The system lists every passenger that boarded a queuing PUV and with the use of the
dispatchers’ mobile application, dispatchers can view and remove onboard passengers in a PUV for
any good reasons.
7
Shows queuing and returning PUVs to passengers

With the use of passengers’ mobile application, passengers can view queuing PUVs with the
count of onboard passengers and returning PUVs that will queue again in Ormoc City Public Utility
Vehicle Terminal.

4.2 System Objectives

The system is developed to organize and manage the queuing of PUVs and passengers in
Ormoc City Public Utility Vehicle Terminal, with that said, the system must meet the following
specific requirements:

● Assign passengers automatically with available PUVs that can be boarded.


● Put passengers with no available queuing PUVs going to their destination into the waiting list
and count their numbers.
● Allow the system administrator to set PUVs to returning mode based on the judgment and
transaction between the system’s administrator and PUV driver or PUV operator for waiting
and queuing passengers in the Ormoc City Public Utility Vehicle Terminal.
● Manage queuing PUVs and passengers through dedicated dispatcher’s mobile application.
● Provide update for passengers about currently queuing and returning PUVs through dedicated
passenger’s mobile application.

4.3 System Functions

8
The system has different functionalities to work properly, varying from the type of users and
the application that is used, these functions help the system to fulfill its objectives. In this, part the
functionalities of the navigation menus are listed and described since each of them possesses the
functionalities that the system must deliver. Here is the list of functionalities in the system’s three
different applications dedicated for the system’s administrator, dispatchers, and passengers.

Terminal Administrator’s Web-based Application

1. Login authentication.

Figure 4.3.1 System Administrator’s Web Application log in page.

Based on the actual physical field that the system will be deployed, the ticketing booth
personnel is the only one qualified terminal personnel who can act as the system administrator and is
present to take in charge of everything that happens in the Ormoc City Public Utility Vehicle
Terminal. In view of that fact, the proponents designed the administrator’s web application to only
allow a single administrator account. Figure 4.3.1 shows the screen design of the administrator’s web
application log in page. It is designed to be easily perceptible and domestic to any users. The page
takes the administrator login password and checks if it matches the administrator’s password stored in
the system’s database.

9
2. Sign up for administrator.

Figure 4.3.2 System Administrator’s sign-up page.

This functionality allows the Ormoc Public Terminal administrator to sign up or register
credentials onto the system. Full name of the administrator is no longer needed and is replaced with a
username. The page will ask for the administrator’s username, password, and password confirmation.
After filling all the fields and pressing the next button, the page will redirect to the security questions
page wherein the administrator must answer five static questions that will be needed in case the
administrator will forget the password. The answers will then be stored in the database. Figure 4.3.2
above shows what the sign-up page looks like, and Figure 4.3.3 below shows the security questions
page.

10
Figure 4.3.3 System Administrator's security questions page.

3. Reset password for administrator.

Figure 4.3.4 System Administrator's reset password page.

The password reset function allows the administrator to create new password in case the
administrator forgot the password. Before the administrator can change the password, security
questions must be answered correctly and is the same with the answers that the administrator used
during sign up. Figure 4.3.4 above shows the interface for resetting the password.

11
4. Editing username and profile photo for administrator.

Figure 4.3.5 System Administrator's toggle settings menu.

Figure 4.3.6 System Administrator's edit username and profile photo.

This function enables the administrator to change or edit username and profile picture that is
associated to the administrator’s account which excludes the administrator’s password. Before the
administrator can edit credentials, a password authentication is required for security reasons. Figure
4.3.6 above shows the interface when changing or editing credentials and Figure 4.3.7 below shows
the password authentication interface and Figure 4.3.5 above shows the settings menu that houses the
edit profile option.

12
Figure 4.3.7 System Administrator's password authentication interface.

5. Restore to default credentials.

Figure 4.3.8 Restore to default credentials interface

This function allows the administrator to restore default credentials. The default credentials
are the credentials that is set by default when the system has no registered administrator yet. The
credentials are the only things that can be restored to default and all the other data that is generated by
the system will remain. This function is important because administrator can be replaced by other
newly hired administrator. Figure 4.3.8 above shows the interface for restoring administrator
13
credentials to default. Just like changing or editing profile, restoring default credentials also needs
password authentication like figure 4.3.7 above for security purposes.

6. The add and set dispatcher status navigation menu.

Figure 4.3.9 Add dispatcher and change dispatcher's status

This function enables the administrator to manage dispatcher status and register dispatcher to
the system. Dispatcher status has two states, the dispatcher could be on duty or off duty. When the
dispatcher is off duty, the administrator can set the status of the said dispatcher to off duty and the
dispatcher will not be allowed to use or login to the dispatcher’s mobile application. The on duty state
is the opposite of the off-duty state. To set the dispatcher’s status to on duty and off duty, the
administrator only needs to press the button below the duty column on the right-side table which has
all the lists of registered dispatchers. Full name of the dispatcher, contact number, and address is
needed for the dispatcher to be registered. A four number PIN will also be associated with the
dispatcher’s account. This PIN will be used for logging into the dispatcher’s mobile application.
Figure 4.3.9 above shows the interface for adding dispatcher and changing dispatcher’s status.

14
7. Register and generate PUV (Public Utility Vehicle) QR (Quick Response) code
navigation menu.

Figure 4.3.10 Register and generate PUV QR code interface

This function generates QR for the PUVs and registers PUV. The information needed to
register a PUV are PUVs’ plate number, route, capacity, driver’s full name, driver’s address, driver’s
contact number, operator’s full name, operator’s address, operator’s contact number. Once the PUV is
registered, a QR code will be associated with the PUV that can be scanned by the dispatcher’s mobile
application QR scanner and set the PUV to queuing mode in the system which will then be displayed
on the passenger’s mobile application. Figure 4.3.10 above shows the register and generate PUV
QR’s page interface.

8. Queuing PUVs navigation menu

15
Figure 4.3.11 Queuing PUVs interface

The queuing PUV navigation menu houses the list of queuing PUVs. This shows the list of
PUVs that are scanned by the dispatcher’s mobile application QR scanner. The PUV will stay in
queuing mode until the dispatcher, or the administrator will dequeue it. Green colored row in the table
indicates that the PUV is still not full while red colored row indicates that the PUV is ready to
dequeue and is full. The PUV can be dequeued using the buttons under the dequeue column in the
table. Figure 4.3.11 above shows the interface of the queuing PUVs page.

9. Waiting Passengers navigation menu

16
Figure 4.3.12 Waiting passengers interface.

In this navigation menu, the administrator can monitor currently waiting passengers in the
Ormoc City Public Utility Vehicle Terminal. Every passenger with no available PUV going to their
destination will be counted as waiting passengers. It is important that the dispatcher knows exactly
how many waiting passengers are there, for it is the basis of deciding what PUV needs to return to the
terminal to queue. Figure 4.3.12 above shows the interface of the waiting passengers page.

10. Returning PUVs navigation menu

17
Figure 4.3.13 Returning PUVs interface.

The returning PUVs navigation menu houses the list of all registered PUV. In this section the
dispatcher can set the status of PUVs to returning, which means that there are still PUVs that will
return to the Ormoc City Public Utility Vehicle Terminal to queue. This is significant because the list
of all the returning PUVs will also be displayed on the passenger’s mobile application. The dispatcher
can refer to the waiting passenger count that can be found in the waiting passengers navigation menu
as it is shown in figure 4.3.12 above to best decide what PUV should be contacted and asked to return.
All returning PUVs are based on the transaction between the administrator and the PUV driver. Figure
4.3.13 shows the returning PUVs interface.

11. Dispatcher’s Profile navigation menu


18
Figure 4.3.14 Dispatcher's profile interface

Figure 4.3.15 Editing dispatcher's profile interface

The dispatchers profile navigation menu houses all the registered dispatchers that is working
in Ormoc City Public Utility Vehicle Terminal with their associated information. There are two
buttons within each of the dispatchers profile containers, one is for editing and the other one is for
removing the dispatcher from the list of registered dispatchers. If the “edit dispatcher’s profile” button
is pressed, then a popup modal will be shown with the editable information of the dispatcher as what
is shown in Figure 4.3.15 above. If the “remove dispatcher” button will be pressed, then a
confirmation alert will be shown confirming if the administrator is sure about the action. Figure 4.3.14
above shows the dispatchers profile interface.
19
12. Vehicles profile navigation menu

Figure 4.3.16 Vehicles profile interface

Figure 4.3.17 Editing dispatcher's profile interface

The functionality of the vehicles profile navigation menu is to show the administrator all the
registered PUV in the Ormoc City Public Utility Vehicle Terminal. In this section, the administrator
can remove and edit dispatcher’s information. As it is shown in Figure 4.3.16, each of the vehicle’s
profile container are two buttons colored blue and red. The blue button is used for editing PUVs’
stored information in the system and the red button is used for removing all the stored information of
the PUVs in the system. If the administrator will edit or change the stored information of a particular
20
PUV, then a popup modal will be displayed as what is depicted in Figure 4.3.17 above. The modal has
all the information of the PUV and allows the administrator to change or edit the information.

13. Vehicle passenger logs navigation menu

Figure 4.3.18 Vehicle passenger logs interface

Figure 4.3.19 Vehicle and passenger logs PDF format

The vehicle and passenger logs navigation menu contain all the logs that are created from the
dequeued vehicles. The logs contain the following information, the driver and operator’s name of the
PUV, the name of the onboard passengers of the PUV, the time the PUV queued and the time it
21
departed from Ormoc City Public Utility Vehicle Terminal, the companion column in the table
indicates if the passenger had some companion when boarded in the PUV. The administrator can save
the logs in PDF format. Figure 4.3.19 shows the screen design of the printable PDF format logs.
Figure 4.3.18 above shows the vehicle passenger logs interface.

Dispatcher’s Mobile Application

1. Dispatcher’s login authentication

22
Figure 4.3.20 Dispatcher's application log in screen.

For the dispatcher to log in, the dispatcher’s application only requires the four-digit PIN that was
generated by the system from the time the dispatcher was registered. The dispatcher can only log in
and use the application if the administrator permits it and set the dispatcher’s status into on duty
mode.

2. Dispatcher’s scanner bottom navigation menu

Figure 4.3.21 QR code scanner’s Figure 4.3.22 QR code scanner’s Figure 4.3.23 Bottom sheet for
bottom navigation menu bottom navigation menu setting destination and
scanning a PUV QR code. scanning a SafeOrmocV2 QR companion of the passenger.
code.

The scanner bottom navigation menu houses the QR code scanner that will scan both the PUV
QR code and SafeOrmocV2 QR code for passengers as shown in Figure 4.3.21 and Figure 4.3.22,
respectively. It can distinguish if the scanned QR code is valid. Simply means, it will only accept QR
code that was generated by the SafeOrmocV2 website and if it came from the administrator’s QR
code generator for PUV. Figure 4.3.22 shows that the passenger is already onboard HVM-101- plate
number of the PUV the passenger boarded. PUV plate number will be the basis on which PUV the
passenger is assigned and boarded. In case an invalid QR code will be scanned, the scanner will throw
an error just as what is shown in Figure 4.3.24 below. The QR code scanner can also determine if the
SafeOrmocV2 QR code for passengers is already registered. If it is already registered and the
destination and companion is already set in the bottom sheet shown in Figure 4.3.23 above, then the
passenger’s QR will be processed and be assigned with a PUV. On the other hand, if the QR code is
not yet registered, an alert notification after setting the destination and companion will be shown
23
asking the dispatcher to register the QR code as what is shown in Figure 4.3.25 below. If the
dispatcher will proceed in registering the passenger’s QR code, then a bottom sheet will be shown
with fields asking for the passengers full name and mobile number as it is shown in Figure 4.3.26
below. After registering the passenger successfully, it can be re-scanned again and can be directly
assigned with a PUV.

Figure 4.3.24 Bottom navigation Figure 4.3.25 Alert shown if Figure 4.3.26 Bottom sheet for
menu scanner throwing an error passenger's SafeOrmocV2 is not registering unregistered
for invalid QR code. yet registered. passenger’s SafeOrmocV2 QR
code.

24
3. Queuing PUVs bottom navigation menu

Figure 4.3.27 List of queuing Figure 4.3.28 PUV information


PUVs and onboard passengers.

The queuing PUV navigation menu houses the list of PUVs that are currently queuing in the
Ormoc City Public Utility Vehicle Terminal. The dispatchers can take a look at these PUVs and can
dequeue them by pressing the x icon on the right just as what is shown in Figure 4.3.27 above.
Pressing the PUV containers will navigate to the PUV information which contains the operator and
driver’s name. It is also where the list of onboard passengers can be seen and where the dispatcher can
unload passengers. Figure 4.3.28 above shows the PUV information interface.

25
4. Dispatcher’s manual queuing bottom navigation menu

Figure 4.3.29 Manual queuing's


interface

Manual queuing is an option for the dispatchers if the passenger has no SafeOrmocV2 QR
code in hand, using this way, the passenger will still be included in the manifest or report logs. The
downside with manual queuing is that it bypasses the checking of passengers that are already loaded,
so there is a higher chance of repetitive loading of passenger to the PUV which affects the accuracy of
the logs, but the situation is easily noticeable, and the dispatcher can just unload the passenger if it
appears repeatedly in the list of passengers in a particular PUV or if the passenger does not exist
onboard. The manual queue will only need the passenger’s full name, contact number, and a PIN will
be generated automatically by the application as the passenger’s unique key. Figure 4.3.29 above
shows the manual queuing forms and fields.

26
5. Dispatcher’s profile bottom navigation menu

Figure 4.3.30 Profile screen


interface design

The profile navigation menu is where dispatcher’s profile resides. It contains the dispatcher’s
name and profile picture. It is also where the dispatcher can log out from the application. Figure
4.3.30 above shows the screen design for the dispatcher’s profile.

27
Passenger’s Mobile Application

1. Passenger’s QR bottom navigation menu

Figure 4.3.31 QR interface Figure 4.3.32 Using the camera Figure 4.3.33 Choosing QR
design. to register and scan image to be scanned and
SafeOrmocV2 QR code. registered with the help of image
gallery applications.

28
The QR bottom navigation menu contains the functionalities for registering QR codes and
managing QR codes for the passenger. In this navigation menu, the passenger can register the
SafeOrmocV2 QR code. Passengers are allowed only to register and store three SafeOrmocV2 QR
code in the application. Removing the QR code in the application will also remove it in the system’s
database which requires internet connectivity for the action to be completed. In Figure 4.3.31 above,
there are two buttons, namely, scan QR and scan image. The scan QR option will navigate to the
screen for scanning QR code using the phone’s camera as what is shown in Figure 4.3.32 above. The
scan image, on the other hand, will ask the passenger to choose what image gallery to open if the
passenger has multiple image gallery application and let the passenger choose what QR code image to
be scanned as what is shown in Figure 4.3.33 above.

2. Queuing PUVs bottom navigation menu

Figure 4.3.34 Queuing PUVs


interface design.

In the queuing PUVs navigation menu, the list of all currently queuing PUV will be viewed
by the passenger. This includes the capacity of the PUV and the number of passengers onboard. All
the PUVs that are on the list are based on those PUVs that were scanned by the dispatcher and set to
queuing mode successfully. Figure 4.3.34 above shows the interface for the queuing PUVs screen.

29
3. Returning PUVs bottom navigation menu

Figure 4.3.35 Returning PUV's


interface design.

Returning PUVs navigation menu contains the list of returning PUVs. These are PUVs that
will still return to the Ormoc City Public Utility Vehicle Terminal to queue. Returning PUVs are
determined by the transaction that was made by the driver and the system administrator. If the PUV
driver agrees with the administrator to return for some reasons, then the system administrator is clear
to set the PUV to returning mode. Figure 4.3.35 above show the interface for the returning PUVs
screen.

4.4 System Scope and Limitation

Ormoc City Public Utility Vehicle Terminal is the location of the area where the system will
be deployed, considering the objective of the system which is to organize and manage the queuing of

30
PUV and passengers, there will be areas that are beyond the scope of the system. In here the scope
and limitation of the system will be discussed.

Scopes of the system

● The PUVs that will be served by the system are PUVs with route going to Ormoc-Sabang-
Bao, Ormoc-Puertobello, Ormoc-Valencia, and Ormoc-Albuera.
● The passengers that will be served by the system are passengers going to the following
destinations, namely Puertobello, Albuera, Sabang-Bao, and Valencia.
● The passenger application will only show queuing and returning PUVs with routes going to
Puertobello, Albuera, Sabang-Bao, and Valencia.
● The dispatcher application will only manage the queuing PUVs and passengers with routes
going to Puertobello, Albuera, Sabang-Bao, and Valencia.
● SafeOrmocV2 and system generated QR code for PUVs is the only valid QR code that the
system accepts.
● The system will only generate a log of every PUV that has a route going to Puertobello,
Valencia, Sabang-Bao, and Albuera that departed after queuing from Ormoc City Public
Utility Vehicle Terminal.

Limitations of the system

● The system does not allow multiple system administrator’s account because it just doesn’t
make sense, the design of the system administrator’s signup process is the same with most
desktop operating systems’ method, email and other online credentials are not required and
the only way to recover the password is correctly answering the security questions that will be
asked during signup process.
● The system does not serve PUVs with a route other than Puertobello, Sabang-Bao, Albuera,
and Valencia, because only the said four routes are experiencing congestion during weekday
and especially during rush hours.
● Other activities in Ormoc City Public Utility Vehicle Terminal are not supported by the
system, the system is solely developed to manage the queuing of PUVs and passengers in
Ormoc City Public Utility Vehicle Terminal.
● Passenger going to destination other than Puertobello, Sabang-Bao, Albuera, and Valencia is
not included to be assisted by the passenger application and dispatcher application, because
the system does not have the capability to add or support other routes, the supported routes
are static and embedded in the system.
● QR codes other than SafeOrmocV2 QR code and system generated QR code for PUVs are not
supported by the system, the system will reject or throws an error if invalid QR code will be
scanned by the dispatcher.
● The system will not create a log from a PUV that has not been scanned by the dispatcher and
is not in the queuing PUV list of the system, all queuing PUV that is supported by the system
must already be scanned, in this way the PUV will be included in the queuing PUV list of the
system and will be feed unto passenger’s application, dispatcher’s application, and system
administrator’s web-based application.
● The hardware components involved in the system’s operation excluding smartphones cannot
operate without electrical power source, it is in the hands of Ormoc City Public Utility
Vehicle Terminal’s management personnel to provide backup electrical power source in the
case of electrical power outage.

31
4.5 Physical Environment and Resources

There are sets of hardware and software resources including target user requirements that are
needed to implement and execute the system.

Hardware resources

1. Desktop/Laptop (Personal Computers) – A desktop/laptop computers are end user


computers that are designed to be used by non-computer expert individuals, it’s functions can
be easily operated and familiarize by average individuals. The desktop/laptop computers will
be used by the system administrator to access the web-based system administrator application.

2. Server Computer – A server computer is a special type of computer; its role is to serve other
computers like end user computers (personal desktop/laptop). Servers listens to request from
other computers and serves them content/data based on what the request is. Server computer
will house the QRMOC – Passenger Queuing Assistance System’s vital algorithms and logic
as well as the web-based system administrator application.

3. Smartphone (Android) – A mobile computing device, smartphone is where the passenger


and dispatcher application will be installed, the specific type of smartphone that is required to
be used is android smartphone.

In order to make the system fully functional, it is required to attain at least the minimum
requirements for each hardware peripherals. Hardware requirements shortcomings may result to
process degradation. (See Appendix B for more detailed hardware specification)

Software Resources

1. Desktop/Laptop operating system (Windows 7 to Windows 10 version release or any


Linux distros) – Operating system to be used in web-based application for administrator.

2. Browsers (Google Chrome, Mozilla Firefox, Brave, Microsoft Edge etc.) – Intended
browser in using the web-based application.

3. Ubuntu Server v21.04 – Operating system to be used in server-side of the application.

4. Apache web server – A program that will be installed in server computer handles protocols
and security that is vital in storing and serving information/data. It will be used to store and
serve information/data generated by users and the system.

32
5. MySQL database – Database service, a relational database system used for storing data.

6. Android 7 (Nougat) to Android 11 (R) Operating System – Operating system to be used in


mobile application for dispatcher and passenger.

It is required to use the mentioned software. Lacking component may result to system failure
and application may not function properly.

Target User Requirements

The application requires specific users who will validate and process several data to make the
system fully functional. The users must meet these special set of skills:

1. Administrator – media and information basic knowledge have prior knowledge interacting
computers and smartphones, expertise on his line of work, human skills (is concerned with
working with people)
2. Dispatcher – media and information basic knowledge, smartphone interaction knowledge,
expertise on his line of work and human skills (is concerned with working with people)
3. Passenger – smartphone interaction knowledge

Basically, administrator must acquire media and information basic knowledge so there will be
no misleading information within the area. It is also essential that administrator should have prior
knowledge on how to interact on computers and smartphones. Simple navigation skills, typing skills,
and simple troubleshooting is required. Dispatcher should also acquire the set of skills the
administrator has. If the administrator is not around, the dispatcher can carry out the duty of the
administrator. Lastly, passengers are also required to possess the set of knowledge on how to interact
with a smartphone. Simple smartphone navigation and a good eye for reading will execute the set of
tasks in hand.

33
4.6 Architectural Design

System Architecture

Passenger
Dispatcher Administrator

INTERNET

LINUX OPERATING SYSTEM

WebSocket Server Apache Server

MySQL Database

Figure 4.6.1 System Architecture

34
The figure shows the system architecture of Qrmoc. The interaction of the components and the
parties involved can be seen in the figure, lines that has arrows at each tip indicates full duplex
connections (data can be transmitted back and forth at the same time). Only the dispatcher (green
arrow) and administrator (gray arrow) has the capability of full duplex connection, they are both
connected to the WebSocket server, the one that handles real-time/full-duplex connection. Dispatcher,
passenger, and the administrator are all connected to the Apache server which processes requests from
the three connected entities/clients. Apache server only supports half duplex connection (data can
only be transmitted in one direction at a time), connection from the server will be lost after client and
server transaction. The MySQL database stores the data/information of the passengers, administrator,
dispatchers, and data/information generated by the system. The Apache server is the mediator
between the end user application and the database because Apache has the capability to communicate
with MySQL securely and process data retrieved from the MySQL database. All parties involved can
communicate and exchange data/information through network (internet), the servers are the one
responsible for the processing and storing of data, so it is important that the server must always be
running and is connected to the network (internet).

35
Data Flow Diagram

Figure 4.6.2 Administrator’s Data Flow Diagram

36
Figure 4.6.2 shows data flow in administrator’s web-based application. It will start in
Administrator and will proceed to login, there will be a database interaction to verify the login details.
Verified login can proceed to several processes which also shares exact database interaction to their
perspective databases as you can see in the figure.

Figure 4.6.3 Dispatcher’s Data Flow Diagram

37
Figure 4.6.3 shows the data flow in dispatcher’s mobile application. It will start in dispatcher
and will proceed to login which will be verified and check the database if the user is registered.
verified login can proceed to several processes which also shares exact database interaction to their
perspective databases as you can see in the figure.

Figure 4.6.4 Passenger’s Data Flow Diagram

Figure 4.6.4 shows the data flow in passenger’s mobile application. It will start in passenger
and can proceed to several processes which also shares exact database interaction to their perspective
databases as you can see in the figure.

In data flow diagram, the processes are labeled as 1.0 onwards, whole number with decimal
or the box with color on top. By executing these processes, the line will show where the data is
transferred or what data is being transferred. The rectangle shape represents the table name which is
located in the database or other data storage schemes (JSON, arrays).

Structured Chart

A structured chart represents hierarchical structure of modules. It breaks down the entire
system into lowest functional modules, describe functions and sub-functions of each module of a
system to a greater detail. (See Appendix C for the system’s structured charts)

38
Database Schema

Figure 4.6.5 Database Schema

This figure shows the data dictionary of each table in the database. Each table consist of fields
that holds information which is being used by the application itself. Information is also stored in this
manner.

39
5.0 Design and Implementation Issues

In developing the system, the proponents encountered some problem or issues on the
technology that are used, some of these resides on the system’s mobile application. The list are as
follows:

Real-Time Data Update

The proponents use React Native in developing the mobile applications for passengers and
dispatchers. React-native is a JavaScript framework used for developing native apps for android and
IOS devices. JavaScript is a web technology but when it comes to react-native, JavaScript behaves
differently compared to when it is applied in the web or executed in the browser. The proponents
encountered a problem in creating an algorithm on implementing real-time update and exchange of
data between the administrator and dispatchers, and dispatcher to dispatcher. At first the proponents
applied the setInterval function to execute another function that will request data from the server. The
setInterval function will run on the background based on the time interval that is set into it, but react-
native does not allow this type of algorithm to be used for updating data. WebSocket is the proponents
last resort, WebSocket can provide full duplex connection between administrator and dispatcher, and
dispatcher to dispatcher. With WebSocket the proponents came out with an algorithm that sends a
signal to each of the connected devices in the WebSocket, once the signal is received by the other end,
the other end will automatically send a request to the server so that everything is updated on each side.

Here is the implementation of setInterval function to fetch the list of queuing PUVs from the server:

setInterval(()=>{retrieveList()}, 5000);

The retrieveList function is executed every five seconds because the time interval is in 5000
milliseconds. The retrieveList function holds the algorithm for fetching the list of queuing PUVs and
updating the current list in the passenger’s application. This method works for a moment but will soon
throw an error indicating that the method is not good to be used and should be replaced.

Here is the alternative method used by the proponents using WebSocket:

ws.send('LOADCHANGES');

ws.onmessage = (e) => {


if(e.data === 'LOADCHANGES'){
retrieveList();
}
}

The ws.send method is executed every time the dispatcher will remove or dequeue a PUV
from the list of queuing PUVs, ws.send will send a message/signal ‘LOADCHANGES’ to the
WebSocket server, the message/signal will then be broadcast to the system administrator and other
dispatchers and when the message/signal will be receive, the ws.onmessage method will then be
executed and the retrieveList function will also be executed.

40
WebSocket Reliability

During the application of WebSocket to the system, the proponents found out another
problem related to WebSocket, the proponents found out that WebSocket automatically disconnects
clients connected to it after a long period of idle, the proponents fixed this problem by creating an
algorithm that sends data to the server continuously in a given time interval, in this way, the
WebSocket server will always regard all the devices connected to it as active devices and
disconnection from the WebSocket server will be avoided.

React-Native Fetch Blob Module

The proponents use a react-native module called react-native fetch blob, it is a third-party
module, and is not shipped during react-native installation. The proponents use this module to fetch
blob objects from the server, specifically an image. During installation of the application in debugging
mode, the module raises a warning. Below is the warning raised by the module.

WARN Require cycle: node_modules\rn-fetch-blob\index.js ->


node_modules\rn-fetch-blob\polyfill\index.js -> node_modules\rn-
fetch-blob\polyfill\Blob.js -> node_modules\rn-fetch-blob\index.js

Require cycles are allowed, but can result in uninitialized values.


Consider refactoring to remove the need for a cycle.

The cause of the warning is importing the rn-fetch-blob module to App.js file. Below is the
code on importing the rn-fetch-blob module in App.js file.

import RNFetchBlob from 'rn-fetch-blob';

The warning was just ignored because everything works as expected. But as the development
of the system continues and changes were made on the method that was previously applied on the
algorithms, the proponents decided to replace the react-native fetch blob module and just go with the
simpler method of linking image sources to the passenger and dispatcher application, in this way the
proponents got rid of the warning and reduces the size of the application by removing the module.
The code below is the alternative method the proponents used.

<Image
style = {{
width: 140,
height: 140,
borderRadius: 100,
borderWidth: 4,
borderColor: '#00a2e8',
}}
source = {profileURL == null ?
require('./assets/profile.png') : {uri: 'http://119.92.152.243' +
profileURL.slice(1)}}
/>

41
Here, the alternative method will only request for the image file from the server, compared to
react-native fetch blob that has a lot of requirements and parameters.

React-Native Performance

React-native was chosen in developing the system’s mobile applications because of the
proponents’ experience and familiarity of JavaScript. React-native is a well-known framework for
building beautiful UI for mobile applications, not only that, but the development period using react-
native is short compared to other native languages. The downside of react-native is the lack of
components, this means that the proponents had to rely on third party components to create a complex
function for the applications. React-native release APK is slower compared to other native languages
application output performance. In the case of the proponents’ system’s mobile application,
performance does not really impact the overall functions and purpose of the application.

Asynchronous JavaScript and XML (AJAX)

The web-based application that was developed by the proponents for the system’s
administrator uses AJAX, a new method in making request from a server and updating the HyperText
Markup Language (HTML) Document Object Model (DOM) without reloading the whole web page.
Relying on server side languages like HyperText Preprocessor (PHP) to handle server request and
reply would force the web page to reload, the proponents thinks that it should be better if reloads will
be minimized in the system’s administrator web-based application because it might become extremely
annoying sometimes if by only pressing a button would require the whole web page to reload just to
load the changes to the screen, it can sometimes contribute to a bad user experience. There were some
functionality also that really needs AJAX to work as designed, just like real-time update for the count
of waiting passengers, queuing vehicles, and returning vehicles, and everything that needs real time
update would require AJAX as a method to handle server request and reply, this is because AJAX can
run in the background without interrupting the user, time interval can also be set to schedule or
repeatedly make AJAX send a request to the server, AJAX is very useful in developing the system
administrator’s web-based application.

Here is an example of the proponents implementation of AJAX to set PUV into returning mode.
Normally, this method will work but the only downside is that it will reload the whole page.

<a href="../admin_vehicle_returning_process.php?
returning='false'">Return</a>

Compared to AJAX that smoothly runs on the background and updates DOM without reloading the
whole page.

function vehicleStatus(data){
const changeVehicleStatus = new XMLHttpRequest();
changeVehicleStatus.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == "success-on"){
returningSetSuccess('Vehicle set to return');
}
else if(this.responseText == "success-off"){
42
returningSetSuccess('Vehicle set to not return');
}
else{
returningSetError('Something went wrong');
}
}
}
changeVehicleStatus.open("POST",
"../admin_vehicle_returning_process.php", true);
changeVehicleStatus.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
changeVehicleStatus.send("data=" + data);
}

JavaScript Object Notation (JSON)

One of the major data structures used by the system is JSON. JSON is useful in formatting
data to be sent to the server and data coming from the server. The power of JSON comes from its
flexibility and simplicity, combined with the JavaScript’s JSON.parse and JSON.stringify functions,
alongside PHP’s json_decode and json_encode functions, then data manipulation and handling will be
smooth during development.

Here is the structure of JSON used for the list of registered vehicles:

{
"vehicle":"UIO-001",
"operator":"Jan Carlo Doyon ",
"driver":"Joelito QuiapoCaorte",
"contact_num":"09306319380",
"route":"valencia",
"capacity":"21",
"queuing":false,
"returning":false
}

6.0 Results and Observation


43
In this chapter, the captured data from several testing processes is presented, analyzed,
described, and interpreted in a systematic manner. The documentation and analysis process aimed to
present data in an intelligible form in order to present the data accurately.

Unit Testing

Unit testing is a type of software testing by which components or individual units are tested in
order to fulfill their functionality. Validation of each unit of the software code if it performs as
expected. The testing of system is conducted until the development of the prototype system not only
in the end of coding. (See Appendix E for the test cases performed by the proponents)

Each module’s functionality is tested accordingly. Mostly, all of the modules test’s expected
result matches the actual result of the test. In some parts of the testing, minor bugs shown up such as
showing a wrong error message upon user error, misspellings, unused buttons and a few more.
Moreover, over all unit testing is successful and the modules and the interface of the application are
working properly.

Integration Testing

In this section, integration testing takes place during and after integration of modules into
main software. Interaction of integrated modules are tested as a group. The proponents conducted an
integration testing to evaluate the integrity and compliance of the components or system with
specified functional requirements. (See Appendix F for the test cases performed by the proponents)

After performing unit testing which focuses on testing of each module functionality,
integration testing takes place. Links between each connected module are tested if the links are
working accordingly. Clicking a link or submitting a form and redirected to the target page is the key
validating if the modules are integrated properly. After the several testing, the proponents conclude
that the modules are properly integrated and the system from administrator’s web-application to
dispatcher and passenger’s mobile application are working properly.

System Testing

This level of testing validates fully integrated and complete software modules. The
proponents ensure an end-to-end evaluation of the system before it was deployed. Testing various
components with several methods.

Test
Case Testing Components Test Objectives Results
ID
Administrator able to login
T-1 Administrator Login Accomplished
successfully

Administrator Fresh Administrator will login by default


T-2 Accomplished
Login / Register password and register

T-3 Administrator Reset Reset password successfully Accomplished


44
Password

Administrator Let user navigate through the


T-4 Accomplished
Dashboard dashboard

Administrator Add &


Add Dispatcher Account and change
T-5 Change Status Accomplished
their on-duty status successfully
Dispatcher

Administrator Reg. & Register PUV and generate QR


T-6 Accomplished
Generate PUV QR Code successfully

Administrator
T-7 Show queuing and dequeue PUVs Accomplished
Queuing PUVs

Administrator Waiting
T-8 Show waiting passengers count Accomplished
Passengers

Administrator Show returning and set returning


T-9 Accomplished
Returning PUVs PUVs

Administrator Show, update and unregistered


T-10 Accomplished
Dispatcher Profile dispatcher profile

Administrator Vehicle Show, update and unregistered


T-11 Accomplished
Profile vehicle profile

Administrator Vehicle Show, save to PDF vehicle


T-12 Accomplished
Passenger Logs passenger logs

T-13 Dispatcher Login Dispatcher able to login successfully Accomplished

Scan PUV and Passenger’s QR


T-14 Dispatcher Scanner Accomplished
Code

Dispatcher Queuing Show, dequeue queuing PUVs and


T-15 Accomplished
PUVs check on-board passengers

Dispatcher Manual Manual queue a passenger


T-16 Accomplished
Queuing successfully

T-17 Dispatcher Profile Show dispatcher profile and logout Accomplished

T-18 Passenger Manage QR Add and check registered QR Codes Accomplished

Passenger Queuing
T-19 Show queuing PUVs Accomplished
PUVs

Passenger Returning
T-20 Show returning PUVs Accomplished
PUVs

Table 6.0.31 System Testing

The result of this testing is successful. All system is working properly as expected. Bugs from
previous testing are fixed in this state.

Acceptance Testing
45
This type of testing is performed by the end user, rating and verifying the software. End to
end business flow validation is the main purpose of this testing. Likert scale is used in this section.
(See Appendix A for questionnaire)

With the help of several entities, testing and gathering of data was attained. Tabular form and
textual discussion of the findings were utilized. There are a total of 50 respondents who participated
on the survey held in Old Ormoc City Terminal and different locations (for passengers). (See
Appendix D for survey documentation)

Graphical User Interface Evaluation

Answer Number of Respondents Percentage


Yes 47 94%

No 3 6%

Total 50 100%

Table 6.0.32 Frequency distribution of question it is simple to use this application

Table 6.0.32 displays that 94% of the respondents are saying the application is simple to use
upon testing. While 3% of the respondents are having hard time using the application.

Answer Number of Respondents Percentage


Yes 45 90%

No 5 10%

Total 50 100%

Table 6.0.33 Frequency distribution of question it was easy to find the information I needed

Table 6.0.33 displays that 90% of the respondents are saying the information displayed are
easy to access upon testing. While 10% of the respondents have difficulties finding desired
information.

Answer Number of Respondents Percentage


Yes 45 90%

No 5 10%

46
Total 50 100%

Table 6.0.34 Frequency distribution of question the organization of information on the application
screen was clear

Table 6.0.34 displays that 90% of the respondents are saying the information displayed are
well organized. While 10% of the respondents are saying that the organization of information is not
accommodated well enough.

Answer Number of Respondents Percentage


Yes 50 100%

No 0 0%

Total 50 100%

Table 6.0.35 Frequency distribution of question the interface of this application was pleasant

Table 6.0.35 displays that 100% of the respondents were fully satisfied of the user interface
(UI) of the application.

Answer Number of Respondents Percentage


Yes 50 100%

No 0 0%

Total 50 100%

Table 6.0.36 Frequency distribution of question the I liked using the interface of this application

Table 6.0.36 displays that 100% of the respondents likes to use the user interface (UI) of the
application.

User Experience Evaluation

47
Answer Number of Respondents Percentage
Yes 22 44%

No 28 56%

Total 50 100%

Table 6.0.37 Frequency distribution of question I found the application complex to use

Table 6.0.37 displays that 44% of the respondents found the application is complex to use.
While there are 66% respondents who says the application is easy to use.

Answer Number of Respondents Percentage


Yes 28 56%

No 22 44%

Total 50 100%

Table 6.0.38 Frequency distribution of question it was easy to learn and use this application

Table 6.0.38 displays that 66% of the respondents says the application is easy to learn and
use. While there are 44% respondents says the application is not easy to learn.

Answer Number of Respondents Percentage


Yes 40 80%

No 10 20%

Total 50 100%

Table 6.0.39 Frequency distribution of question this application has all the functions and capabilities
I expect it to have

Table 6.0.39 displays that 80% of the respondents says the application has all the desired
functions and capabilities. While there are 20% of the respondents who are still not satisfied with the
functions and capabilities the application has.

Answer Number of Respondents Percentage


Yes 42 84%

No 8 16%

Total 50 100%

48
Table 6.0.40 Frequency distribution of question I found the various functions in this application were
well integrated

Table 6.0.40 displays that 84% of the respondents says the application’s functions are well
integrated. While 16% of them disagreed.

Answer Number of Respondents Percentage


Yes 22 44%

No 28 56%

Total 50 100%

Table 6.0.41 Frequency distribution of question I think I would need the support of a technical person
to be able to use this application

Table 6.0.41 displays that 44% of the respondents needs assistance from technical person to
able to use this application, while 56% does not need any assistance using the application.

Answer Number of Respondents Percentage


Yes 37 74%

No 13 26%

Total 50 100%

Table 6.0.42 Frequency distribution of question I would imagine that most people would learn to use
this application quickly

Table 6.0.42 displays that 74% of the respondents says that most people would learn to use
this application quickly, while 26% of them disagree.

Therefore, the proponents conclude that the general respondents of the survey accepted the
application according to the data presented above.

7.0 Conclusion and Recommendations

With the hard work exerted by the proponents, and with the system testing and surveys
conducted by the proponents, the proponents concluded that the project was successful, and the
project’s objective were met, but just like any other developed system, the project still needs
49
continuous research, refinements, and development. There were some limitations and rules that should
be applied in the field where the system will be deployed. Below is the list of rules that terminal
personnel should do in adapting the system to their everyday operations, in other words, these rules
should be implemented because this is the area that is out of the extent of the system’s capability and
should depend on human’s actions and judgments.

● Every passenger’s SafeOrmocV2 QR code should be scanned first before boarding a PUV to
make sure that the passengers are evenly and fairly distributed to each of the queuing PUVs in
the terminal and ensures that the manifest or the log of the PUV will have all the name of the
passengers that boarded.
● Every passenger who will disembark during queuing of the PUV should be re-scanned or be
removed in the list of passengers in that PUV. If the dispatcher will not do these procedures,
then the logs or manifest will be inaccurate and the data that will be feed to the passenger’s
application will be inaccurate.
● The system administrator and dispatchers should keep watch of all the PUVs that are already
full and remove them from the list of queuing PUV as soon as possible so that the passengers
will not be presented with an inaccurate list of queuing PUVs.
● The system administrator should keep watch of the waiting passengers if the passengers are
still waiting so that the administrator can best decide which PUV should be contacted and ask
to return to queue again in the terminal.
● The system administrator should monitor all the dispatchers that are on duty so that their
status can be set to off duty mode and be restricted to log in to the dispatcher’s application.

All the objectives were met by the proponents. However, as the proponents proceeded into
testing the system, the proponents realized that there are still parts that can be improved and
functionalities that should be included. The proponents are not able to develop the missing pieces in
the system because there was no time left for development anymore. The system could be made
perfect if the next project proponent will put these missing pieces to system. Here are the list of
missing functionalities and functionalities that can be improve by the next project proponents.

● The system administrator should have the capability to support other routes so that other PUV
that also queues in the terminal can use the system.
● The system’s application graphical user interface should be enhanced for a more user-friendly
appeal to the users.
● The web-based administrator’s application should be migrated to desktop application because
it is more secure and convenient compared to browsers.
● Drivers should also have a dedicated application wherein drivers can take a look of the
currently waiting passengers and set themselves into returning mode.
● List of waiting passengers should be reset to zero every end of the day.
● Passengers should also have the opportunity to take a look at the image of the PUV and the
driver and operator’s name using the passenger’s application.
● Passenger’s application should also have a real time data update capability just like
dispatcher’s application.
● There should be an option that the system administrator could set to on or off that will let the
system to automatically dequeue a PUV if the PUV is already full.
● There should be a daily report that states the number of PUVs that queued during the day.
● System’s computer server should be connected in the local area network (LAN) but still
accessible on the internet. This method is to avoid heavy data traffic when crossing different
networks. Time is greatly important in the Ormoc City Public Utility Vehicle Terminal and
computer server’s that is located on other network can experience lag and heavy traffic which
will affect the response time of the server.

50
● During administrator sign up, the system should also require the administrator’s active email
address.
● The system should have the capability to know the physical address of the device which the
system administrator is using so that the system will know if the administrator had gain access
to the application using other devices. This action should trigger a security breach and the
system should send a one-time email confirmation link to the administrator’s registered email
address. If the administrator will be able to successfully click the link, then the system will
allow the access of the administrator’s application using the device.

Those are the possible improvements that the current proponents had think about. If the next
proponents have other alternatives that can contribute for the project to achieve its full potential,
then it can also be applied as long as it will still guide the project to its main objectives.

51
References

Ghazal, M., Hamouda, R., & Ali, S. (2015, October). An iot smart queue management system
with real-time queue tracking. In 2015 Fifth International Conference on e-Learning (econf) (pp. 257-
262). IEEE.

Seun, A. E., Bature, U. I., Jahun, K. I., Nasir, A. Y., Hassan, A. M., & Toro, U. S. (2019, October).
Hospital Electronic Queuing Solution System. In 2019 2nd International Conference of the IEEE
Nigeria Computer Chapter (NigeriaComputConf) (pp. 1-7). IEEE.

Cosmas, N. I., Etus, C., Ajere, I. U., & Godswill, A. U. (2015). Online bus ticket reservation
system. Iiard International Journal Of Computer Science And Statistics.

Mahzabeen, A. (2019). Online Bus Ticket Booking System.

Butler, M. (2010). Android: Changing the mobile landscape. IEEE pervasive Computing, 10(1), 4-7.

Guerrouj, L., & Baysal, O. (2016, May). Investigating the android apps' success: An empirical study.
In 2016 IEEE 24th International Conference on Program Comprehension (ICPC) (pp. 1-4). IEEE.

Jain, V., & Sharma, A. (2013). The consumers preferred operating system: Android or
iOS. International Journal of Business Management and Research (IJBMR), 3(4), 29-40.

Eken, S., & Sayar, A. (2014, June). A smart bus tracking system based on location-aware services and
QR codes. In 2014 IEEE International Symposium on Innovations in Intelligent Systems and
Applications (INISTA) Proceedings (pp. 299-303). IEEE.

Ramalho, J. F., Correia, S. F., Fu, L., António, L. L., Brites, C. D., André, P. S., ... & Carlos, L. D.
(2019). Luminescence Thermometry on the Route of the Mobile ‐Based Internet of Things (IoT): How
Smart QR Codes Make It Real. Advanced Science, 6(19), 1900950.

Chen, B., & Cheng, H. H. (2010). A review of the applications of agent technology in traffic and
transportation systems. IEEE Transactions on intelligent transportation systems, 11(2), 485-497.

Dowd, Z., Franz, A. Y., & Wasek, J. S. (2018). A decision-making framework for maintenance and
modernization of transportation infrastructure. IEEE Transactions on Engineering
Management, 67(1), 42-53.

52
Appendix A

Survey Questionnaire

Republic of the Philippines


Eastern Visayas State University – Ormoc City Campus
Brgy. Don Felipe Larrazabal, Ormoc City

Usability Questionnaire
(Q R M O C – Passenger Queuing Assistance Application)

Name (optional): ___________________________ Contact #: _______________

Instruction: Kindly check the box based on your experience using the application.

Graphical User Interface (GUI) Design Evaluation

Questions YES NO

1. It is simple to use this application.

2. It was easy to find the information I needed.

3. The organization of information on the application screen


was clear.
4. The interface of this application was pleasant.

5. I liked using the interface of this application.

Note: The “interface” includes those items that you use to interact with the application. For example, some components of
the interface are the keyboard, the mouse and screens/touchscreens (including their graphics and language.)

User Experience Evaluation

Questions YES NO

1. I found the application complex to use.

2. It was easy to learn and use this application.

3. This application has all the functions and capabilities I


expect it to have.
4. I found the various functions in this application were well
integrated.
5. I think I would need the support of a technical person to
be able to use this application.
6. I would imagine that most people would learn to use this
application quickly.

Appendix B
53
Hardware Requirements Specification

54
Appendix C

Structured Chart

Structured Chart – Administrator

55
Structured Chart – Administrator (Register PUV)

56
Structured Chart – Administrator (Queuing PUVs)

57
Structured Chart – Administrator (Waiting Passengers)

58
Structured Chart – Administrator (Returning PUVs)

59
Structured Chart – Administrator (Add & Manage Dispatcher PUVs)

60
Structured Chart – Administrator (Report Logs)

61
Structured Chart – Administrator (Dispatcher Profiles)

62
Structured Chart – Administrator (Vehicle Profiles)

63
Structured Chart – Dispatcher (Login)

64
Structured Chart – Dispatcher (QR Code Scanner)

65
Structured Chart – Dispatcher (Queuing PUVs)

66
Structured Chart – Dispatcher (Manual Queuing)

Structured Chart – Dispatcher (Profile)

67
Structured Chart – Passenger

68
Structured Chart – Passenger (View QR Code)

69
Structured Chart – Passenger (Queuing PUVs)

70
Structured Chart – Passenger (Returning PUVs)

71
Appendix D

Survey Documentation

An image showing queuing PUVs (Bus, Van, and Multicab) at day.

An image showing queuing PUVs (Van, and Multicab) at night

72
Image showing how the proponent setup the administrator web page inside the ticketing booth where
the administrator is located

Image showing the administrator interacting with the application

73
Image showing the front view of the ticketing booth

Image showing the queuing multicabs

74
Image showing the terminal without queuing PUVs (multicab) and queuing passengers

Image showing queuing passengers

75
Image showing the proponent conducting a testing by explaining how the application works

Image showing how the dispatcher interact with the mobile application

76
Image showing how the other dispatcher interact with the mobile application

Image showing how the dispatcher interact with the QR Code scanner in mobile application

77
Image showing dispatcher’s interaction with the mobile application

Image showing how the proponent register the passenger’s QR Code on the application

78
Image showing how the passenger interact with the mobile application

79
Appendix E

Test Case: Unit Testing

Terminal Administrator’s Web-based Application

Module: Administrator Login

Test Test Description How to Test? Test Data Expected Results


Case
ID
1) In Qrmoc Administrator Upon entering the correct
Login, input default Default default password, create
A-1 Fresh Login
password “admin” Password new account page will
2) Press “Enter” to login show

1) Input the correct created


account during the fresh It will show the
A-2 Login Password
login administrator dashboard
2) Press “Enter” to login

1) Input incorrect
A-3 Login Error password Password An error will show
2) Press “Enter” to login

Leave Fields 1) Press “Enter” without


A-4 An error will show
Blank entering any data.

Table 6.0.1 Administrator Login

Sub-Module: Fresh Login

Test Test Description How to Test? Test Data Expected Results


Case
ID
1) Input several data
(username, password
Username, password ang
and profile picture Username,
Register New image is saved and will be
A-1 which is optional) Password,
Account redirected to security
2) Press “Enter” or Image
questions page
“Next” button to
proceed

1) Press “Enter” or click


the “Next button”
Leave Fields It will show the
A-2 while leaving the
Blank administrator dashboard
fields blank
2) Press “Enter” to login

Table 6.0.2 Fresh Login

80
Sub-Module: Reset Password (1)

Test Test Description How to Test? Test Data Expected Results


Case
ID
1) Input the correct answer
in security questions Security Correct validation will
A-1 Validate Answer 2) Press “Enter” or click Questions show the password
the “Validate” button to Answers reset page
proceed

1) Input incorrect
Security
password
A-2 Validate Error Questions An error will show
2) Press “Enter” or click
Answers
the “Validate” button

Leave Fields 1) Press “Enter” without


A-3 An error will show
Blank entering any data.

Table 6.0.3 Reset Password (1)

Sub-Module: Reset Password (2)

Test Test Description How to Test? Test Data Expected Results


Case
ID
1) Input new desired
New password updated,
password
A-1 Reset Password Password and will be redirected to
2) Press “Enter” or click the
Login page
“Reset” button to proceed

1) Input old password


Input Old
A-2 2) Press “Enter” or click the Password An error will show
Password
“Validate” button proceed

2) Press “Enter” or “Next”


Leave Fields
A-3 button without entering An error will show
Blank
any data.

Table 6.0.4 Reset Password (2)

Sub-Module: Security Questions

Test Test Description How to Test? Test Data Expected Results


Case
ID
A-1 Answer Security 1) Input answer Security Security question
Questions appropriate to questions Questions answers are saved and
2) Press “Enter” or click Answers will be redirected to
the “Sign-up” button to
81
proceed Login page

1) Press “Enter” or click


Leave Fields the Sign-up” button
A-2 An error will show
Blank without entering any
data.

Table 6.0.5 Security Questions

Module: Administrator Dashboard

Test Test Description How to Test? Test Expected Results


Case Data
ID
1) After logging in to Qrmoc The page will be
Go to Register
A-1 Administrator, Click Register redirected to Register
PUV (1)
PUVs “More” button PUV page

1) Click Reg. & Generate PUV QR


The page will be
Go to Register in sidebar of the page which is
A-2 redirected to Register
PUV (2) located on the left side of the
PUV page
page.

The page will be


Go to Queuing 1) Click “More” button under
A-3 redirected to Queuing
PUVs (1) Queuing PUVs in Dashboard
PUVs page

1) Click Queuing PUVs in sidebar The page will be


Go to Queuing
A-4 of the page which is located on redirected to Queuing
PUVs (2)
the left side of the page PUVs page

The page will be


Go to Dispatcher 1) Click “More” button under
redirected to
A-5 Add & Change Registered Dispatcher in
Registered Dispatcher
Status (1) Dashboard
page

1) Click Add & Change Status in The page will be


Go to Dispatcher
sidebar of the page which is redirected to
A-6 Add & Change
located on the left side of the Registered Dispatcher
Status (2)
page page

The page will be


Go to Dispatcher
1) Click “More” button under On redirected to
A-7 Add & Change
Duty Dispatchers in Dashboard Registered Dispatcher
Status (3)
page

1) Click Waiting Passengers in


The page will be
Go to Waiting sidebar of the page which is
A-8 redirected to Waiting
Passengers located on the left side of the
Passengers page
page

A-9 Go to Returning 1) Click Returning Passengers in The page will be


PUVs sidebar of the page which is redirected to
located on the left side of the Returning Passengers
82
page page

1) Click Dispatcher Profile in The page will be


Go to Dispatcher sidebar of the page which is redirected to
A-10
Profile located on the left side of the Dispatcher Profile
page page

1) Click Vehicle Profile in sidebar The page will be


Go to Vehicle
A-11 of the page which is located on redirected to Vehicle
Profile
the left side of the page Profile page

1) Click Vehicle Passengers Logs


The page will be
Go to Vehicle in sidebar of the page which is
A-12 redirected to Vehicle
Passenger Logs located on the left side of the
Passengers Logs page
page

The page will be


Go to 1) Click Dashboard in sidebar of
redirected to
A-13 Administrator the page which is located on the
Administrator
Dashboard (1) left side of the page
Dashboard page

The page will be


Go to 1) Click “Qrmoc” in sidebar of the
redirected to
A-14 Administrator page which is located on the left
Administrator
Dashboard (2) side of the page
Dashboard page

1) Click “Administrator Profile” in The page will be


Go to
sidebar of the page which is redirected to
A-15 Administrator
located on the left side of the Administrator
Dashboard (3)
page Dashboard page

The page will be


Go to 1) Click Home in Navigation bar
redirected to
A-16 Administrator which is located on the top side
Administrator
Dashboard (4) of the page
Dashboard page

1) Click the Gear icon in


Navigation bar which is located
A-17 Go to Edit Profile on the top-right side of the page A modal will appear
2) A drop-down will show and
click Edit Profile

1) Click the Gear icon in


Navigation bar which is located
Go to Reset
A-18 on the top-right side of the page A modal will appear
Default Password
2) A drop-down will show and
click Reset Default

1) Click the Gear icon in


The session will be
Navigation bar which is located
ended and the page
A-19 Logout on the top-right side of the page
will be redirected to
2) A drop-down will show and
Login page
click Logout

A-20 Full screen 1) Click the Expand Arrow icon in The page will expand
Navigation bar which is located to full screen

83
on the top-right side of the page
and clicking it again revert it
changes

1) Click the Bars button in


Navigation bar which is located
The sidebar will
A-21 Collapse sidebar on the top-right side of the page
collapse
and clicking it again revert it
changes

Table 6.0.6 Administrator Dashboard

Sub-Module: Edit Administrator Profile

Test Test Description How to Test? Test Data Expected Results


Case
ID
1) After clicking edit
profile, input the
Correct password
Authenticate password and click
A-1 Password authentication will show the
User the “authenticate”
edit profile
button

1) Click the
Leave Password “authenticate” button
A-2 An error will show
Fields Blank without entering any
data.

1) Click the Pencil icon


on the image and The selected image will
select image in your replace the image shown
Image,
A-3 Edit Profile local file storage previously and after clicking
Username
2) Input new username the commit changes, the
3) Click the “commit new profile will be saved
changes”

Leave Profile 1) Click “commit


Picture and changes” button Image. An information error will
A-4
Username without changing the Username show
unchanged data

1) Click “x” button


A-5 Close Modal (1) located on the upper- The modal will be closed
right of the modal

2) Click outside the


A-6 Close Modal (2) The modal will be closed
modal

Table 6.0.7 Edit Administrator Profile

84
Sub-Module: Reset Default Password

Test Test How to Test? Test Data Expected Results


Case Description
ID
1) After clicking the reset
default password in
administrator dashboard, a The password will be reset
Reset
modal will show to default, the session will
A-1 Password to Password
2) Input password be ended and the page will
Default
3) Click authenticate button be redirected to Login page
4) A modal will appear
5) Click the reset button

1) Click “x” button located


Close Modal
A-2 on the upper-right of the The modal will be closed
(1)
modal

Close Modal
A-3 2) Click outside the modal The modal will be closed
(2)

Table 6.0.8 Reset Default Password

Module: Dispatcher Add & Change Duty Status

Test Test How to Test? Test Data Expected Results


Case Description
ID
1) After clicking the Add
& Change Status in
administrator sidebar,
the page will show
2) Check first the tooltip
before each label
3) Input the required
dispatcher’s
information After clicking the register
Name,
4) Leave the suffix section button, the dispatcher’s
Mobile
Register empty if you dispatcher information will be
A-1 Number,
Dispatcher does not have suffix on registered and it will be
Address,
their name displayed on the right side
PIN, Image
5) Click the Generate Pin of the page.
button that will be used
by the dispatcher to
login in dispatcher
mobile application
6) Upload a photo by
clicking the cross icon
7) Click the Register
Dispatcher button

85
1) Use your mouse to
Information A brief instruction will be
A-2 hover information icon
Tooltip shown
before each label

1) Input numbers or
special characters on
Name,
name fields
Mobile
Name Input 2) Fill the rest of the field
A-3 Number, An error will show
Error with required
Address,
information
PIN, Image
3) Click the Register
Dispatcher button

1) Input letters on mobile


number field Name,
2) Fill the rest of the field Mobile
Mobile
A-4 with required Number, An error will show
Number Error
information Address,
3) Click the Register PIN, Image
Dispatcher button

1) Click the Register


Leave
Dispatcher button
A-5 Password An error will show
without entering any
Fields Blank
data.

1) After clicking the Add


& Change Status in Name,
Display
administrator sidebar, Mobile Registered Dispatcher will
A-6 Registered
the page will show Number, be displayed on a data table
Dispatcher
2) View the right side of PIN, Duty
the page

The color of the circle will


1) View the right side of
be changed, a success alert
Change the page
will display and dispatcher
A-7 Dispatcher 2) In data table, Click the Duty
can or cannot login in
Duty Status circle icon under the
mobile application
Duty’s column
depending on the status.

Table 6.0.9 Dispatcher Add & Change Duty Status

Module: Register and Generate PUV QR

Test Test How to Test? Test Data Expected Results


Case Description
ID
A-1 Register PUV 1) After clicking the Plate Number, After clicking the register
Register and Generate Route, PUV button, the dispatcher’s
PUV QR in Capacity, Name, information will be
administrator sidebar, Mobile Number, registered and it will be
the page will show Address, Image displayed on the right
2) Check first the tooltip
86
before each label
3) Input the required
PUV information
4) Input the required
operator’s
information
5) Input the required
driver’s information
6) Leave the suffix
side of the page.
section empty if the
driver and operator’s
does not have suffix
on their name
7) Upload a vehicle
photo by clicking the
cross icon
8) Click the Register
Vehicle button

1) Use your mouse to


Information A brief instruction will
A-2 hover information
Tooltip be shown
icon beside each label

1) Input numbers or
special characters on
Plate Number,
name fields
Route, PUV
Name Input 2) Fill the rest of the
A-3 Capacity, Name, An error will show
Error field with required
Mobile Number,
information
Address, Image
3) Click the Register
PUV button

1) Input letters on
mobile number field Plate Number,
2) Fill the rest of the Route, PUV
Mobile
A-4 field with required Capacity, Name, An error will show
Number Error
information Mobile Number,
3) Click the Register Address, Image
PUV button

Leave 1) Click the Register


A-5 Password PUV button without An error will show
Fields Blank entering any data.

1) After clicking the


Display Generated QR Code will
Registering the PUV
A-6 Generated QR Code be displayed the right
a QR Code will be
QR Code side of the page
generated

1) Registered Generated
Save The QR Code will be
QR Code will be
A-7 Generated QR Code saved in the file storage
displayed
QR Code as PDF
2) Click the Save button

Table 6.0.10 Register and Generate PUV QR

87
Module: Queuing PUVs

Test Test How to Test? Test Data Expected Results


Case Description
ID
1) After clicking the
Queuing PUVs in
Plate Number, After clicking a certain
administrator
Route, Operator, route, the data table will
Sort Queuing sidebar, the page will
A-1 Driver, Route, show the sorted data from
PUVs show
Passenger the chosen route first and
2) Click the dropdown
Capacity the rest
3) Click a route you
want to sort

1) Use your mouse to


Information A brief instruction will be
A-2 hover information
Tooltip shown
icon before label

Plate Number, Upon typing the vehicle


1) Click the search box Route, Operator, plate number, it will
Search
A-3 2) Input vehicle plate Driver, Route, automatically show the
Vehicle
number Passenger closest plate number on
Capacity typed vehicle plate number

1) In data table, under


dequeue column,
Dequeue The PUV will be dequeued
A-4 there is dequeue Queue PUV
PUV from queuing list
button
2) Click dequeue button

1) Check the color If the row is color green,


Full Capacity
A-5 queuing PUV row if Queue PUV the PUV is not full and red
Indicator
green or red if it is full

Table 6.0.11 Queuing PUVs

Module: Waiting Passengers

Test Test How to Test? Test Data Expected Results


Case Description
ID
1) After clicking the Waiting The waiting
Show Waiting Waiting
A-1 Passengers in administrator passengers count
Passengers passengers
sidebar, the page will show is displayed

Table 6.0.12 Waiting Passengers

Module: Returning PUVs

Test Test How to Test? Test Data Expected Results

88
Case Description
ID
1) After clicking the
Returning PUVs in Plate Number, After clicking a certain
Sort administrator sidebar, Route, route, the data table will
A-1 Queuing the page will show Operator, show the sorted data from
PUVs 2) Click the dropdown Driver, Route, the chosen route first and
3) Click a route you Mobile Number the rest
want to sort

1) Use your mouse to


Information A brief instruction will be
A-2 hover information
Tooltip shown
icon before label

Plate Number, Upon typing the vehicle


1) Click the search box Route, plate number, it will
Search
A-3 2) Input vehicle plate Operator, automatically show the
Vehicle
number Driver, Route, closest item on typed
Mobile Number vehicle plate number

1) In data table, under The PUV will be set to


returning column, returning or not. If the
Returning
A-4 there is circle button Queue PUV circle button color yellow
PUV
2) Click the circle it is set to returning and not
button if it is color black

Table 6.0.13 Returning PUVs

Module: Dispatchers Profile

Test Test How to Test? Test Data Expected Results


Case Description
ID
1) After clicking the Name, Address,
Show Registered Dispatcher
Dispatcher Profile in Mobile
A-1 Registered profiles will be
administrator sidebar, Number, PIN,
Dispatcher displayed on screen
the page will show Image

1) Click the search box


Name, Address, Upon typing the name,
2) Input the Name of the
Mobile it will automatically
A-2 Search Vehicle dispatcher (either first
Number, PIN, show the closest item
name, middle name or
Image on typed name
last name)

Name, Address,
Edit A modal will show
Mobile
A-4 Dispatcher 1) Click the edit button after clicking the edit
Number, PIN,
Profile button
Image

A-5 Unregistered 1) Click the Unregistered Dispatcher The dispatcher profile


Dispatcher button Profile will be deleted
2) An alert will show,
click the Unregistered
89
button

Table 6.0.14 Dispatchers Profile

Sub-Module: Edit Dispatcher Profile

Test Test Description How to Test? Test Data Expected Results


Case
ID
1) After clicking the Edit
button in dispatcher Name,
The Dispatcher
profile page, a modal Address,
Profile will be
A-1 Edit Profile will show Mobile
updated and the
2) Edit desired fields Number, PIN,
modal will disappear
3) Click Save Changes Image
button

1) Use your mouse to


Information A brief instruction
A-2 hover information icon
Tooltip will be shown
before label

Name,
1) On edit dispatcher A warning alert will
Save Changes Address,
modal, click Save show and dispatcher
A-3 without editing Mobile
Changes button without profile is not
profile Number, PIN,
editing a single data changed
Image

1) Input numbers or special Name,


characters on name Address,
Name Input
A-4 fields Mobile An error will show
Error
2) Click the Save Changes Number, PIN,
button Image

1) Input letters on mobile


number field Name,
2) Fill the rest of the field Address,
Mobile Number
A-5 with required Mobile An error will show
Error
information Number, PIN,
3) Click the Save Changes Image
button

Table 6.0.15 Edit Dispatcher Profile

Module: Vehicles Profile

Test Test How to Test? Test Data Expected Results


Case Description
ID
A-1 Show 1) After clicking the Plate Number, Registered Dispatcher
Registered in Vehicle profile Route, PUV profiles will be
PUVs sidebar, the page Capacity, Name,
90
Mobile Number,
will show displayed on screen
Address, Image

1) Click the search Plate Number,


Upon typing the name,
box Route, PUV
Search it will automatically
A-2 2) Input the plate Capacity, Name,
Vehicle show the closest item
number of the Mobile Number,
on typed plate number
vehicle Address, Image

Plate Number,
Edit Route, PUV A modal will show
1) Click the edit
A-4 Dispatcher Capacity, Name, after clicking the edit
button
Profile Mobile Number, button
Address, Image

1) Click the Remove


button
Remove The PUV profile will
A-5 2) An alert will show, PUV Profile
Dispatcher be deleted
click the
Unregistered button

After clicking the QR


Download QR Code Code, it will be
A-6 1) Click the QR Code
QR Code Information downloaded in your file
storage

Table 6.0.16 Vehicles Profile

Sub-Module: Edit Vehicle Profile

Test Test Description How to Test? Test Data Expected


Case Results
ID
Plate Number,
1) After clicking the Edit The Vehicle
Route, PUV
button in vehicle profile Profile will be
Capacity,
A-1 Edit Profile page, a modal will show updated and the
Name, Mobile
2) Edit desired fields modal will
Number,
3) Click Save Changes button disappear
Address, Image

1) Use your mouse to hover A brief


Information
A-2 information icon before instruction will
Tooltip
label be shown

Plate Number,
1) On edit vehicle modal, Route, PUV A warning alert
Save Changes
click Save Changes button Capacity, will show and
A-3 without editing
without editing a single Name, Mobile vehicle profile
profile
data Number, is not changed
Address, Image

A-4 Name Input Error 1) Input numbers or special Plate Number, An error will
characters on name fields Route, PUV show
Capacity,
91
Name, Mobile
2) Click the Save Changes
Number,
button
Address, Image

1) Input letters on mobile Plate Number,


number field Route, PUV
Mobile Number 2) Fill the rest of the field Capacity, An error will
A-5
Error with required information Name, Mobile show
3) Click the Save Changes Number,
button Address, Image

Table 6.0.17 Edit Vehicle Profile

Module: Vehicle Passenger Logs

Test Test How to Test? Test Data Expected Results


Case Description
ID
1) After clicking the
Vehicle Passenger Logs
in administrator
sidebar, the page will After clicking a certain sorting
show arrangement, the data table will
Sort Queuing
A-1 2) Click the dropdown Logs show the sorted data from the
PUVs
3) Click sorting chosen sorting arrangement
arrangement you want first and the rest
to sort (latest, oldest,
alphabetical and by
time/date)

1) Use your mouse to


Information A brief instruction will be
A-2 hover information icon
Tooltip shown
before label

Upon typing the vehicle plate


1) Click the search box Plate
Search number, it will automatically
A-3 2) Input vehicle plate Number,
Vehicle show the closest item log/s on
number Logs
typed vehicle plate number

A printable report will show


1) Click any plate
A-4 Check Logs Logs upon clicking a plate
number/item displayed
number/item

Upon clicking the Save PDF


1) On clicked plate
button, the printable report will
A-5 Save Logs number/item, click Logs
be saved as PDF and can be
Save PDF button
stored in file storage

Table 6.0.18 Vehicle Passenger Logs

Dispatcher’s Mobile Application

92
Module: Login

Test Test How to Test? Test Expected Results


Case Description Data
ID
2) Open Qrmoc Upon entering correct PIN, it will
Dispatcher mobile automatically login and will be
D-1 Login PIN
application redirected to dispatcher QR scanner or
3) Input PIN Qrmoc dispatcher dashboard

3) Input incorrect
D-2 Login Error PIN An error will show
PIN

2) Do not connect
the Internet After opening the application, it will
No Internet
D-3 3) Open the Qrmoc not proceed to login and will be stuck
connection
Dispatcher mobile in loading screen
application

Table 6.0.19 Login

Module: QR Code Scanner

Test Test Description How to Test? Test Expected Results


Case Data
ID
1) Login to application
2) Touch the circle
button with QR code
icon to scan
3) Focus the camera on
registered
Scan Registered SafeOrmocV2 QR The scanned passenger QR code
QR
D-1 Passenger QR code to scan it will be queued, an alert tone will
Code
Code 4) Touch the route also ring and an alert text show
button where the
passenger going
5) Touch the with or no
companion button
according to
passenger

D-2 Scan 1) Touch the circle QR The scanned passenger QR code


Unregistered button with QR code Code will be queued, an alert tone will
Passenger QR icon to scan also ring and an alert text show
Code 2) Focus the camera on
unregistered
SafeOrmocV2 QR
code to scan it
3) An alert will prompt,
touch the OK button

93
to register
4) Fill the required fields
5) Touch the Register
button

1) Touch the circle


button with QR code After scanning, the PUV will be
Scan PUV QR QR
D-3 icon to scan queued, alert tone will ring and
Code Code
2) Focus the camera on an alert text will show
QR code to scan it

1) Touch the circle After scanning, alert tone will


button with QR code ring and an alert text will show
Scan the same QR
D-4 icon to scan (“Passenger is already loaded
QR Code Code
2) Focus the camera on on” for passenger and “Vehicle
QR code to scan it already queuing” for PUV

1) Touch the circle


Scan not button with QR code
QR
D-5 SafeOrmocV2 icon to scan An alert error will show
Code
QR Code 2) Focus the camera on
QR code to scan it

Table 6.0.20 QR Code Scanner

Module: Queuing PUVs

Test Test Description How to Test? Test Data Expected Results


Case
ID
Show Queuing 1) Touch PUVs on bottom Queuing Queuing PUVs
D-1
PUVs navigation bar PUVs will be displayed

1) Touch the “x” red button The PUV will be


D-2 Dequeue PUV PUV data
2) Confirm dequeue dequeued

After scanning,
Queuing the PUV will be
Check Boarding 1) Touch any item listed or PUVs, queued, alert tone
D-3
Passenger touch the plate number text Queuing will ring and an
Passenger alert text will
show

1) Touch any item listed or The passenger


Dequeue Boarding
D-4 touch the plate number text QR Code will be removed
Passenger
2) Touch the “x” red button from the list

Table 6.0.21 Queuing PUVs

Module: Manual Queuing

Test Test How to Test? Test Data Expected


94
Case Description Results
ID
1) Touch the Manual Queue on
bottom navigation bar Name,
The passenger
2) Fill required fields Mobile
D-1 Manual Queue is manually
3) Touch with or no companion Number,
queued
button Route
4) Touch load passenger button

1) Input numbers and special


characters under name (first
name, middle name and last Name,
Name Input name) Mobile An error will
D-2
Error 2) Fill the remaining fields Number, show
3) Touch with or no companion Route
button
4) Touch load passenger button

1) Input letters and special


characters under mobile
Name,
number
Mobile Number Mobile An error will
D-3 2) Fill the remaining fields
Input Error Number, show
3) Touch with or no companion
Route
button
4) Touch load passenger button

Table 6.0.22 Manual Queuing

Module: Profile

Test Test How to Test? Test Expected Results


Case ID Description Data
5) Touch the Profile on Name, The Dispatcher Profile will
D-1 Check Profile
bottom navigation bar Image show

5) Touch the Logout Upon pressing the logout button,


D-2 Logout
button you will be redirected to login

Table 6.0.23 Profile


95
Passenger’s Mobile Application

Module: QR Code

Test Test Description How to Test? Test Expected Results


Case Data
ID
6) Open Qrmoc passenger
mobile application QR
Show Registered Registered QR Code will be
P-1 7) If you are not in QR Code,
QR Code displayed
tab, touch the QR on Name
bottom navigation bar

6) Touch the Scan QR


button with camera
icon to scan
7) Focus the camera on
Register Name, The QR Code Information
unregistered
P-2 SafeOrmocV2 Mobile will be saved and will be
SafeOrmocV2 QR
QR Code (1) Number shown on QR tab
code to scan it
8) Fill the required fields
9) Touch the Register
button

3) Touch the scan image


button with QR code
icon
Register 4) Upload SafeOrmocV2 Name, The QR Code Information
P-3 SafeOrmocV2 QR Code image from Mobile will be saved and will be
QR Code (2) your local file storage Number shown on QR tab
5) Fill the required fields
6) Touch the Register
button

3) Touch the circle button


with QR code icon to Name,
Register the
P-4 scan Mobile An error will show
same QR Code
4) Focus the camera on Number
QR code to scan it

3) Touch the circle button


Scan not with QR code icon to
P-5 SafeOrmocV2 scan QR Code An error will show
QR Code (1) 4) Focus the camera on
QR code to scan it

1) Touch the circle button


with QR code icon to
Scan not
scan
P-6 SafeOrmocV2 QR Code An error will show
2) Upload SafeOrmocV2
QR Code (2)
QR Code image from
your local file storage

96
Table 6.0.24 QR Code

Module: Queuing PUVs

Test Test Description How to Test? Test Data Expected Results


Case
ID
Show Queuing 1) Touch PUVs on bottom Queuing Queuing PUVs will
P-1
PUVs navigation bar PUVs be displayed

1) In PUVs tab, on top side


of the screen touch other
Navigate to Queuing Queuing PUVs will
P-2 route to navigate
different route PUVs be displayed
2) Swiping on each route to
navigate is also possible

Table 6.0.25 Queueng PUVs

Module: Returning PUVs

Test Test How to Test? Test Data Expected Results


Case Description
ID
Show Returning 1) Touch Returning on bottom Returning Returning PUVs
P-1
PUVs navigation bar PUVs will be displayed

1) In Returning tab, on top side


of the screen touch other
Navigate to Returning Returning PUVs
P-2 route to navigate
different route PUVs will be displayed
2) Swiping on each route to
navigate is also possible

Table 6.0.26 Returning PUVs

97
Appendix F

Test Case: Integration Testing

Module: Login, Registration, Reset Password

Test
Case Test Case Objective Test Case Description Expected Results
ID
Check the interface
link between the Enter default login credentials and To be directed to the
A-1
Login and click on the Login button Registration
Registration

Check the interface


link between
From Register, fill the required To be directed to Answer
A-2 Registration and
fields and click on the Next button Security Questions
Answer Security
Questions

Check the interface


From Add Answer Security
link between Add
A-3 Questions, fill the required fields To be directed to Login
Answer Security
and click on the Sign-up button
Questions and Login

Check the interface


link between Login From Login, enter the login To be directed to
A-4
and Administrator credentials and press “Enter” Administrator dashboard
dashboard

Check the interface


From Login, click the Reset To be directed to Answer
A-5 link between Login
Password Security Questions
and Reset Password

Check the interface


From Answer Security Questions,
link between Answer To be directed to Reset
A-6 fill the questions correctly and click
Security Questions Password
on the Validate button
and Reset Password

Check the interface From Reset Password, enter your


A-7 link between Reset new password and click on the To be directed to Login
Password and Login Reset button

Table 6.0.27 Login, Registration

Module: Administrator Dashboard

Test
Case Test Case Objective Test Case Description Expected Results
ID
A-1 Check the interface From Administrator Dashboard, To be directed to each
98
perspective page (Add &
Change Status
Dispatcher, Reg. &
Generate PUV QR,
Queuing PUVs, Waiting
link in dashboard click each tab item
Passengers, Returning
PUVs, Dispatcher
Profile, Vehicle Profile
and Vehicle Passenger
Logs)

Table 6.0.28 Administrator Dashboard

Module: Scan PUV and Passenger QR Code

Test
Case Test Case Objective Test Case Description Expected Results
ID
Scanned QR Code will
be stored and queued.
From Dispatcher Mobile
Scan QR Code for Passenger, Administrator
A-1 Application, touch the scan button
Queuing and Dispatcher can view
to Scan QR Code
queued passenger and
PUV

Table 6.0.29 Scan PUV and Passenger QR Code

Module: Vehicle Profile and Dispatcher Profile

Test
Case Test Case Objective Test Case Description Expected Results
ID
Review the profile and Edit desired profile and click save To be redirected to
A-1
interface links changes to edit details Administrator dashboard

Table 6.0.30 Vehicle Profile and Dispatcher Profile

99
Appendix G

Resource Persons

Engr. Joseph Jaymel Morpos


Faculty
Information Technology Department
Eastern Visayas State University
josephjaymel.morpos@evsu.edu.ph

Engr. Edward B. Bertulfo


Faculty
Information Technology Department
Eastern Visayas State University
edward.bertulfo@evsu.edu.ph

Bryanly Jarito
Software Engineer
Codev
bryanlyj@codev.com

Ruel Medina Mendoza


Dispatcher
Ormoc Terminal Department
LGU of Ormoc City
0951-022-7080

100
Appendix H

Personal Vitae

John Carlo L. Villas


Address: Phase 1 Block 12 Lot 12, Mapulang Lupa, Pandi, Bulacan
Contact Number: 0946-468-1870
E-mail: johncarlo.villas@evsu.edu.ph

Career Objective

To work with a leading company and to use my analytical thinking to the best of my ability
combined with perseverance, so as to contribute to organization’s growth and goal, as well as to attain
my professional goal.

Education
Tertiary Eastern Visayas State University – Ormoc City Campus
Brgy.Don Felipe Larrazabal, Ormoc City, Leyte
S.Y. 2018 – Present

Secondary
Junior High Ramon Magsaysay Cubao High School
Brgy. Pinagkaisahan, Quezon City
S.Y. 2012 – 2014
Virginia Ramirez-Cruz High School
Siling Bata, Pandi, Bulacan
S.Y. 2014 – 2016
Senior High Immaculate Conception International College of Arts and
Technology
Brgy. Borol 1st, Balagtas, Bulacan
S.Y. 2016 – 2018

Elementary Kamuning Elementary School


Brgy. Kamuning, Quezon City
S.Y. 2006 – 2012

Affiliations and Organizations


A.Y. 2018-2019 Representative, Unified Information Technology Society (UNITS)

101
A.Y. 2014-2015 Member. Supreme Student Government (SSG) VRCHS
A.Y. 2014-2015 Member. Math Club at VRCHS
A.Y. 2011-2014 Member, Altar Server at National Shrine of Mount Carmel Parish

Personal Background
Date of Birth: October 13, 1999
Place of Birth: Pasay, Metro Manila
Civil Status: Single
Gender Male
Religion: Roman Catholic

Technical Skills
● Computer Literate
● Oriented in Computer Programming such as:
o C
o PHP
o JavaScript
o HTML
o CSS
o Laravel Framework (PHP)
o React-Native (JavaScript)
o Visual Basic
● Oriented in Microsoft Office applications such as:
o Microsoft Office Word
o Microsoft Office Excel
o Microsoft Office Powerpoint

102
Jancarlo S. Doyon
Address: Brgy. Cabulihan Ormoc City, Leyte
Contact Number: 0970-664-0105
E-mail: Jancarlo.doyon@evsu.edu.ph

Career Objective

To work with a leading company and to use my analytical thinking to the best of my ability
combined with perseverance, so as to contribute to organization’s growth and goal, as well as to attain
my professional goal.

Education
Tertiary Eastern Visayas State University – Ormoc City Campus
Brgy.Don Felipe Larrazabal, Ormoc City, Leyte
S.Y. 2018 – Present

Secondary Valencia National High School (VNHS)


S.Y. 2009 - 2010
New Ormoc City National High School (NOCNHS)
S.Y. 2004 – 2007

Elementary Ormoc City SpEd Center (OCSC)


S.Y. 1998 – 2004

Affiliations and Organizations


A.Y. 2018-2019 Member, Unified Information Technology Society (UNITS)
Personal Background
Date of Birth: January 31, 1991
Place of Birth: Ormoc City, Leyte Philippines
Civil Status: Single
Gender Male
Religion: Christian

Technical Skills
● Computer Literate
● Oriented in Computer Programming such as:
o C
o PHP
o JavaScript
103
o HTML
o CSS
o Laravel Framework (PHP)
o React-Native (JavaScript)
o Visual Basic
● Oriented in Microsoft Office applications such as:
o Microsoft Office Word
o Microsoft Office Excel
o Microsoft Office Powerpoint

104
Joelito Q. Caorte
Address: Brgy. Bagong Buhay, Ormoc City, Leyte
Contact Number: 0955-776-1208
E-mail: joelitoqcaorte@gmail.com

Career Objective

To apply my skills and put into use the knowledge I harnessed during my study to an
organization that operates in the field of Information Technology and gaining lessons and experience
along the way that leads to the development of my professional career.

Education
Tertiary Eastern Visayas State University – Ormoc City Campus
Brgy. Don Felipe Larrazabal, Ormoc City, Leyte
S.Y. 2018 – 2022

Secondary
Junior High New Ormoc City National High School (NOCNHS)
Brgy. Don Felipe Larrazabal, Ormoc City, Leyte
S.Y. 2012 – 2016
Senior High AMA Computer Learning Center (ACLC) College Ormoc
Lopez Jaena St, Ormoc City, Leyte
S.Y. 2016 – 2018

Elementary San Isidro Elementary School


Brgy. San Isidro, Ormoc City, Leyte
S.Y. 2006 – 2012

Personal Background
Date of Birth: February 08, 2000
Place of Birth: Ormoc City, Leyte
Civil Status: Single
Gender Male
Religion: Roman Catholic

Technical Skills
● Computer System Servicing
● Mobile Application Development
● Web Development
105
● Strong Knowledge in Computer Languages such as:
o C
o PHP
o JavaScript
o HTML
o CSS
o Laravel Framework (PHP)
o React-Native (JavaScript)
o Visual Basic

106
Appendix I

System Source Code

MySQL Database Connection

Database connection used all throughout (PHP):

<?php
$server = 'localhost';
$username = 'jcube';
$password = '94z&Vk9A4X5K';
$dbname = 'ocqms';

try{
$connection = new PDO("mysql:host=$server;dbname=$dbname",
$username, $password);
$connection->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e){
echo "error";
exit();
}

Terminal Administrator’s Web-based Application

1. Log in

107
Log in elements class and ID (HTML):

<div class="uname">
<span id="uname"></span>
</div>
<div class="password-container">
<a href="javascript:;" id="icon"><i class="icon fas fa-
eye"></i></a>
<input name="pass" placeholder="password" type="password"
class="cred" id="pass_word">
</div>

Fetching the stored admin username and admin image profile directory from database (JavaScript):

function loadAdminImage(){
const loadImage = new XMLHttpRequest();
loadImage.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == 'error'){
document.getElementById('message').innerHTML = "Something is
wrong";
}else{
let data = JSON.parse(this.responseText);
document.getElementById('profile-image').src =
'auth_process/' + data.profile;
document.getElementById('uname').innerHTML = data.name;
}
console.log(this.responseText);
}
}
loadImage.open("POST",
"./auth_process/auth_process_load_image.php", true);
loadImage.send();
}

Fetching process for admin username and admin image profile directory (PHP):

<?php
require "../db_connection.php";
try{
$name_and_photo = $connection->prepare("SELECT Uname, Profile FROM
admin");
$name_and_photo->execute();
$result = $name_and_photo->fetchAll();
if(sizeof($result) > 0){
foreach($result as $data){
echo json_encode(array("name" => $data['Uname'], "profile" =>
$data['Profile']));
}
}else{
echo "error";
108
}
}catch(Exception $e){
echo "error";
}
?>

When pressing the enter key on the keyboard, sign in process will proceed and will call this function
(JavaScript):

document.getElementById('pass_word').addEventListener('keyup',
function(key){
if(key.keyCode == "13"){
signin();
}
if(document.getElementById('pass_word').value == ''){
if(document.getElementById('message').innerHTML != ''){
document.getElementById('message').innerHTML = '';
}
}
})

Sending the admin’s username and password to the server (JavaScript Code):

const signin = () => {


let uname = document.getElementById('uname').innerHTML;
let pass = document.getElementById('pass_word').value;
if(uname.trim() == '' || pass.trim() == ''){
document.getElementById('message').innerHTML = 'Enter your
password';
}else{
var signInProcess = new XMLHttpRequest();
signInProcess.onreadystatechange = function () {
if(this.readyState == 4 && this.status == 200) {
if(this.responseText == "default"){
window.location.replace('./signup');
}
else if(this.responseText == "notfound"){
document.getElementById('message').innerHTML =
"Authentication failed";
}
else if(this.responseText == 'error_connection'){
document.getElementById('signin-info').style.display =
'block';
document.getElementById('info-message').innerHTML =
'Connection error';
document.getElementById('admin-signin').value = 'Sign in';
}
else if(this.responseText == 'login'){
window.location.replace('./ormocterminal/dashboard');
}
else{

109
document.getElementById('message').innerHTML = "Something
went wrong";
}
console.log(this.responseText);
}
}
signInProcess.open("POST",
"./auth_process/auth_process_signin.php", true);
signInProcess.setRequestHeader("Content-type", "application/x-
www-form-urlencoded");
signInProcess.send("uname=" + uname + "&pass=" + pass);
}
}

Authenticating the username and password entered by the administrator (PHP):

<?php
session_start();
if(isset($_POST['uname']) && isset($_POST['pass'])){
if(!empty(trim($_POST['uname'])) && !
empty(trim($_POST['pass']))){
try{
require '../db_connection.php';
$verify_admin = $connection->prepare("SELECT COUNT(*) FROM
admin WHERE Uname= :username AND Password= :password");
if(trim($_POST['uname']) === 'admin' && $_POST['pass'] ===
'admin'){
$username = trim($_POST['uname']);
$password = sha1($_POST['pass']);
$verify_admin->bindParam(':username', $username);
$verify_admin->bindParam(':password', $password);
$verify_admin->execute();
$still_admin = $verify_admin->fetchColumn();
if($still_admin > 0){
echo "default";
$_SESSION['default'] = true;
}
else{
echo "notfound";
}
}
else{
$username = trim($_POST['uname']);
$password = sha1($_POST['pass']);
$verify_admin->bindParam(':username', $username);
$verify_admin->bindParam(':password', $password);
$verify_admin->execute();
$verified_admin = $verify_admin->fetchColumn();
if($verified_admin > 0){
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $_POST['uname'];
echo 'login';
}
110
else{
echo "notfound";
}
}
}catch(Exception $e){
echo "error";
}
}
}
$connection = null;
?>

2. Sign up

Sign up elements (HTML):

<div class="signup-main-container">
<div class="page">
<span>Sign up</span>
</div>
<div class="admin-prof-container">
<div title="Upload profile picture (Optional)">
<img id="actual-pic"
src="./auth_process/images/adminUserProfile.png">
<div class="front-word" onclick="openFile()"
title="Upload profile picture">
<span class="fas fa-plus"></span>
</div>
<div class="back-element">
<input tabindex="1" id="profile-pic" type="file"
accept="image/*">
</div>
</div>
111
</div>
<div>
<input tabindex="2" maxlength="20" placeholder="username"
name="uname" type="text" class="cred" id="u_name">
</div>
<div class="password-container">
<a href="javascript:;" id="icon"><i class="icon fas fa-
eye"></i></a>
<input tabindex="3" name="pass" placeholder="password"
type="password" class="cred" id="pass_word">
</div>
<div class="password-container">
<a href="javascript:;" id="conf-icon"><i class="icon fas
fa-eye"></i></a>
<input tabindex="4" name="conf" placeholder="confirm
password" type="password" class="cred" id="conf_pass">
</div>
<div class="validate-holder-cred">
<button tabindex="5" class="validate-cred"
onclick="next()">Next</button>
</div>
<span id="message"></span>
</div>

When pressing the next button (JavaScript):

const next = () => {


let uname = document.getElementById('u_name').value;
let f_pass = document.getElementById('pass_word').value;
let s_pass = document.getElementById('conf_pass').value;
if(uname.trim() == ''){
document.getElementById('message').innerHTML = 'Username is
required';
}
else if(f_pass.trim() == '' || s_pass.trim() == ''){
document.getElementById('message').innerHTML = 'Password is
required';
}
else if(f_pass != s_pass){
document.getElementById('message').innerHTML = 'Password did not
match';
}
else if((f_pass == s_pass) && (f_pass.length < 8 && s_pass.length
< 8)){
document.getElementById('message').innerHTML = 'Password is less
than eight characters';
}
else{
document.querySelector('.questions-main-
container').style.display = 'flex';
document.querySelector('.signup-main-container').style.display =
'none';
}
112
}

3. Sign up security questions

Security questions’ elements (HTML):

<div class="questions-main-container">
<div class="holder">
<h4>Security questions</h4>
<p>In case you forget your password</p>
</div>
<br>
<div class="holder">
<div>
<label for="q-1">What is your favorite color?</label>
</div>
<div>
<input name="q_one" class="answers" type="text" id="q-
1">
</div>
</div>
<div class="holder">
<div>
<label for="q-2">What is your mother's maiden
name?</label>
</div>
<div>
<input name="q_two" class="answers" type="text" id="q-
2">
</div>
</div>
<div class="holder">
<div>

113
<label for="q-3">What elementary school did you
attend?</label>
</div>
<div>
<input name="q_three" class="answers" type="text"
id="q-3">
</div>
</div>
<div class="holder">
<div>
<label for="q-4">When you were young, what did you
want to be when you grew up?</label>
</div>
<div>
<input name="q_four" class="answers" type="text"
id="q-4">
</div>
</div>
<div class="holder">
<div>
<label for="q-5">What is the name of the town where
you were born?</label>
</div>
<div>
<input name="q_five" class="answers" type="text"
id="q-5">
</div>
</div>
<div class="validate-holder">
<button class="validate" onclick="signup()">Sign
up</button>
</div>
<span id="mess"></span>
</div>

When pressing the sign-up button (JavaScript):

const signup = () => {


let uname = document.getElementById('u_name').value;
let f_pass = document.getElementById('pass_word').value;
let s_pass = document.getElementById('conf_pass').value;
let first_answer = document.getElementById('q-1').value;
let second_answer = document.getElementById('q-2').value;
let third_answer = document.getElementById('q-3').value;
let fourth_answer = document.getElementById('q-4').value;
let fifth_answer = document.getElementById('q-5').value;

if(uname.trim() == ''){
document.getElementById('mess').innerHTML = 'Username is
required';
}
else if(f_pass.trim() == '' || s_pass.trim() == ''){

114
document.getElementById('mess').innerHTML = 'Password is
required';
}
else if(f_pass.trim() != s_pass.trim()){
document.getElementById('mess').innerHTML = 'Password did not
match';
}
else if(first_answer.trim() == '' || second_answer.trim() == '' ||
third_answer.trim() == '' || fourth_answer.trim() == '' ||
fifth_answer.trim() == ''){
document.getElementById('mess').innerHTML = 'Please answer all
the questions';
}
else if((f_pass.trim() == s_pass.trim()) && (f_pass.trim().length
< 8 && s_pass.trim().length < 8)){
document.getElementById('mess').innerHTML = 'Password is less
than eight characters';
}
else{
var signUpProcess = new XMLHttpRequest();
signUpProcess.onreadystatechange = function () {
if(this.readyState == 4 && this.status == 200){
if(this.responseText == "changed"){
document.getElementById('mess').innerHTML = 'Admin is
already set';
}
else if(this.responseText == "success"){
uploadPhoto(uname);
}
else if(this.responseText == "reset"){
document.getElementById('mess').innerHTML = 'Something
went wrong';
}
else if(this.responseText == "severe"){
document.getElementById('mess').innerHTML = 'Something
severe happened';
}
else{
document.getElementById('mess').innerHTML = 'Something
went wrong';
}
console.log(this.responseText);
}
}
signUpProcess.open("POST",
"./auth_process/auth_process_signup.php", true);
signUpProcess.setRequestHeader("Content-type", "application/x-
www-form-urlencoded");
signUpProcess.send("uname=" + uname.trim() + "&password=" +
f_pass + "&first_answer=" + first_answer.trim() +
"&second_answer=" + second_answer.trim() + "&third_answer=" +
third_answer.trim() + "&fourth_answer=" +
fourth_answer.trim() + "&fifth_answer=" + fifth_answer.trim());
}
}
115
Process for saving security questions’ answers and admin’s username and password into the database
(PHP):

<?php
session_start();
if(isset($_POST['uname']) && isset($_POST['password']) &&
isset($_POST['first_answer']) && isset($_POST['second_answer']) &&
isset($_POST['third_answer'])
&& isset($_POST['fourth_answer']) &&
isset($_POST['fifth_answer'])){
if(!empty(trim($_POST['uname'])) && !
empty(trim($_POST['password'])) && !
empty(trim($_POST['first_answer'])) && !
empty(trim($_POST['second_answer']))
&& !empty(trim($_POST['third_answer'])) && !
empty(trim($_POST['fourth_answer'])) && !
empty(trim($_POST['fifth_answer']))){
require '../db_connection.php';
try{
$verify_admin = $connection->prepare("SELECT COUNT(*)
FROM admin WHERE Uname = :username AND Password = :password");
$default_username = 'admin';
$default_password = sha1('admin');
$verify_admin->bindParam(':username',
$default_username);
$verify_admin->bindParam(':password',
$default_password);
$verify_admin->execute();
$still_admin = $verify_admin->fetchColumn();
if($still_admin > 0){
$username = trim($_POST['uname']);
$password = sha1($_POST['password']);
$store_credentials = $connection->prepare("UPDATE
admin SET Uname = :username, Password = :password WHERE Uname
= :uname AND Password = :pass");
$store_credentials->bindParam(':username',
$username);
$store_credentials->bindParam(':password',
$password);
$store_credentials->bindParam(':uname',
$default_username);
$store_credentials->bindParam(':pass',
$default_password);
$store_credentials->execute();
if($store_credentials->rowCount() > 0){
$first_answer = sha1(strtolower(preg_replace('/\
s+/', '', $_POST['first_answer'])));
$second_answer = sha1(strtolower(preg_replace('/\
s+/', '', $_POST['second_answer'])));
$third_answer = sha1(strtolower(preg_replace('/\
s+/', '', $_POST['third_answer'])));
$fourth_answer = sha1(strtolower(preg_replace('/\
s+/', '', $_POST['fourth_answer'])));

116
$fifth_answer = sha1(strtolower(preg_replace('/\
s+/', '', $_POST['fifth_answer'])));
$question_one = $connection->prepare("UPDATE
questions SET Answer = :answer_one WHERE QuestionId = 1");
$question_two = $connection->prepare("UPDATE
questions SET Answer = :answer_two WHERE QuestionId = 2");
$question_three = $connection->prepare("UPDATE
questions SET Answer = :answer_three WHERE QuestionId = 3");
$question_four = $connection->prepare("UPDATE
questions SET Answer = :answer_four WHERE QuestionId = 4");
$question_five = $connection->prepare("UPDATE
questions SET Answer = :answer_five WHERE QuestionId = 5");
$question_one->bindParam(':answer_one',
$first_answer);
$question_two->bindParam(':answer_two',
$second_answer);
$question_three->bindParam(':answer_three',
$third_answer);
$question_four->bindParam(':answer_four',
$fourth_answer);
$question_five->bindParam(':answer_five',
$fifth_answer);
if($question_one->execute() && $question_two-
>execute() && $question_three->execute() && $question_four-
>execute() && $question_five->execute()){
echo "success";
unset($_SESSION['default']);
}
else{
$store_credentials->bindParam(':uname',
$username);
$store_credentials->bindParam(':pass',
$password);
$store_credentials->bindParam(':username',
$default_username);
$store_credentials->bindParam(':password',
$default_password);
$store_credentials->execute();
if($store_credentials->fetchColumn() > 0){
echo "reset";
}
else{
echo "severe";
}
}
}
}
else{
echo "changed";
}
$connection = null;
}catch(Exception $e){
echo "error";
$connection = null;
}
117
}
}
?>

4. Reset password’s security questions

Sign up security questions elements (HTML):

<div class="questions-main-container">
<div class="holder">
<h4>Security questions</h4>
</div>
<br>
<div class="holder">
<div>
<label for="q-1">What is your favorite color?</label>
</div>
<div>
<input name="q_one" class="answers" type="text" id="q-
1">
</div>
</div>
<div class="holder">
<div>
<label for="q-2">What is your mother's maiden
name?</label>
</div>
<div>
<input name="q_two" class="answers" type="text" id="q-
2">
</div>
</div>
<div class="holder">
118
<div>
<label for="q-3">What elementary school did you attend?
</label>
</div>
<div>
<input name="q_three" class="answers" type="text" id="q-
3">
</div>
</div>
<div class="holder">
<div>
<label for="q-4">When you were young, what did you want
to be when you grew up?</label>
</div>
<div>
<input name="q_four" class="answers" type="text" id="q-
4">
</div>
</div>
<div class="holder">
<div>
<label for="q-5">What is the name of the town where you
were born?</label>
</div>
<div>
<input name="q_five" class="answers" type="text" id="q-
5">
</div>
</div>
<div class="validate-holder">
<button class="validate"
onclick="validate()">Validate</button>
</div>
<span id="mess"></span>
</div>

When pressing the validate button (JavaScript code):

const validate = () => {


let qOne = document.getElementById('q-1').value.replace(/\s+/g,
'');
let qTwo = document.getElementById('q-2').value.replace(/\s+/g,
'');
let qThree = document.getElementById('q-3').value.replace(/\s+/g,
'');
let qFour = document.getElementById('q-4').value.replace(/\s+/g,
'');
let qFive = document.getElementById('q-5').value.replace(/\s+/g,
'');

if(qOne.trim() == '' || qTwo.trim() == '' || qThree.trim() == ''


|| qFour.trim() == '' || qFive.trim() == ''){

119
document.getElementById('mess').innerHTML = 'Please answer all
questions';
}else{
const compareAnswer = new XMLHttpRequest();
compareAnswer.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == 'success'){
window.location.replace('./passwordreset');
}else if(this.responseText == 'notset'){
document.getElementById('mess').innerHTML = 'Default has
not changed';
}else if(this.responseText == 'fail'){
document.getElementById('mess').innerHTML = 'Some answers
did not match';
}else if(this.responseText == 'error'){
document.getElementById('mess').innerHTML = 'Please answer
all the questions';
}else{
document.getElementById('mess').innerHTML = 'Something
went wrong';
}
}
}
compareAnswer.open('POST',
'./auth_process/auth_process_reset.php', true);
compareAnswer.setRequestHeader("Content-type", "application/x-
www-form-urlencoded");
compareAnswer.send('qone=' + qOne + '&qtwo=' + qTwo + '&qthree='
+ qThree + '&qfour=' + qFour + '&qfive=' + qFive);
}
}

Process for validating if the answers to the security questions are correct (PHP):

<?php
session_start();
if(trim($_POST['qone']) == '' || trim($_POST['qtwo']) == '' ||
trim($_POST['qthree']) == '' || trim($_POST['qfour']) == '' ||
trim($_POST['qfive']) == ''){
echo "error";
}else{
require '../db_connection.php';
$default_username = sha1('admin');
$default_password = sha1('admin');
try{
$verify_admin = $connection->prepare("SELECT COUNT(*) FROM admin
WHERE Uname = :username AND Password = :password");
$verify_admin->bindParam(':username', $default_username);
$verify_admin->bindParam(':password', $default_password);
$verify_admin->execute();
$still_admin = $verify_admin->fetchColumn();
if($still_admin > 0){
$connection = null;
120
echo 'notset';
}else{
$qone = sha1(strtolower(preg_replace('/\s+/', '',
$_POST['qone'])));
$qtwo = sha1(strtolower(preg_replace('/\s+/', '',
$_POST['qtwo'])));
$qthree = sha1(strtolower(preg_replace('/\s+/', '',
$_POST['qthree'])));
$qfour = sha1(strtolower(preg_replace('/\s+/', '',
$_POST['qfour'])));
$qfive = sha1(strtolower(preg_replace('/\s+/', '',
$_POST['qfive'])));
$one = false;
$two = false;
$three = false;
$four = false;
$five = false;
$one_value = 1;
$two_value = 2;
$three_value = 3;
$four_value = 4;
$five_value = 5;
$compare_answer = $connection->prepare("SELECT Answer FROM
questions WHERE Answer = :answer AND QuestionId = :questionid");
$compare_answer->bindParam(':answer', $qone);
$compare_answer->bindParam(':questionid', $one_value);
$compare_answer->execute();
if($compare_answer->rowCount() > 0){
$one = true;
}
$compare_answer->bindParam(':answer', $qtwo);
$compare_answer->bindParam(':questionid', $two_value);
$compare_answer->execute();
if($compare_answer->rowCount() > 0){
$two = true;
}
$compare_answer->bindParam(':answer', $qthree);
$compare_answer->bindParam(':questionid', $three_value);
$compare_answer->execute();
if($compare_answer->rowCount() > 0){
$three = true;
}
$compare_answer->bindParam(':answer', $qfour);
$compare_answer->bindParam(':questionid', $four_value);
$compare_answer->execute();
if($compare_answer->rowCount() > 0){
$four = true;
}
$compare_answer->bindParam(':answer', $qfive);
$compare_answer->bindParam(':questionid', $five_value);
$compare_answer->execute();
if($compare_answer->rowCount() > 0){
$five = true;
}

121
if($one && $two && $three && $four && $five){
$_SESSION['reset'] = true;
echo "success";
}else{
$_SESSION['reset'] = false;
echo "fail";
}
}
$connection = null;
}catch(Exception $e){
$connection = null;
echo "error";
}
}

?>

5. Password reset

Password reset components (HTML):

<div class="reset-main-container">
<div class="page">
<span>Reset Password</span>
</div>
<div class="password-container">
<a href="javascript:;" id="icon"><i class="icon fas fa-
eye"></i></a>
<input tabindex="1" name="pass" placeholder="password"
type="password" class="cred" id="pass_word">
</div>
<div class="password-container">

122
<a href="javascript:;" id="conf-icon"><i class="icon fas
fa-eye"></i></a>
<input tabindex="2" name="conf" placeholder="confirm
password" type="password" class="cred" id="conf_pass">
</div>
<div class="validate-holder-cred">
<button tabindex="3" class="validate-cred"
onclick="changePassword()">Reset</button>
</div>
<span id="message"></span>
</div>

When pressing the reset button (JavaScript):

const changePassword = () => {


let f_pass = document.getElementById('pass_word').value;
let s_pass = document.getElementById('conf_pass').value;
if(f_pass.trim() == '' || s_pass.trim() == ''){
document.getElementById('message').innerHTML = 'Please fill all
the fields';
}
else if(f_pass != s_pass){
document.getElementById('message').innerHTML = 'Password did not
match';
}
else if((f_pass == s_pass) && (f_pass.length < 8 && s_pass.length
< 8)){
document.getElementById('message').innerHTML = 'Password is less
than eight characters';
}
else{
changePass = new XMLHttpRequest();
changePass.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == 'success'){
window.location.replace('./signin');
}else if(this.responseText == 'fail'){
document.getElementById('message').innerHTML = 'Unable to
reset password';
}else if(this.responseText == 'error'){
document.getElementById('message').innerHTML = 'Something
went wrong';
}else if(this.responseText == 'restricted'){
document.getElementById('message').innerHTML = 'Not that
fast!';
}else{
document.getElementById('message').innerHTML = 'Something
went wrong';
}
}
}
changePass.open("POST",
"./auth_process/auth_process_passwordreset.php", true);
123
changePass.setRequestHeader("Content-type", "application/x-www-
form-urlencoded");
changePass.send('password=' + f_pass);
}
}

Resetting the password (PHP):

<?php
session_start();
if(isset($_SESSION['reset'])){
if($_SESSION['reset']){
if(trim($_POST['password']) == ''){
echo 'error';
}else{
require '../db_connection.php';
try{
$password = sha1($_POST['password']);
$change_password = $connection->prepare("UPDATE admin SET
Password = :password WHERE AdminId = 1");
$change_password->bindParam(':password', $password);
$change_password->execute();
if($change_password->rowCount() > 0){
unset($_SESSION['reset']);
echo 'success';
}else{
echo 'fail';
}
$connection = null;
}catch(Exception $e){
$connection = null;
echo "error";
}
}
}else{
echo "restricted";
}
}else{
echo "restricted";
}
?>

124
6. Editing administrator’s username and profile photo

Editing username and profile photo components (HTML):

<div class="modal fade" id="editModal" tabindex="-1" role="dialog"


aria-labelledby="editModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content" style="background-color: #EAF2F8">
<div class="modal-header">
<h5 class="modal-title" id="editModalLabel" style="color:
#34495E">Edit profile</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="modal-body-sub-container">
<div class="admin-prof-container">
<div title="Upload profile picture (Optional)">
<img id="replacement-pic" src="">
<div class="front-word" onclick="openExplorer()"
title="Upload profile picture">
<span class="fas fa-pencil-alt"></span>
</div>
<div class="back-element">
<input id="rep-pic" type="file" accept="image/*">
</div>
</div>
</div>
<div class="uname">
<span id="edit-uname"></span>
</div>

125
<div>
<input maxlength="20" placeholder="change username"
name="uname" type="text" class="cred" id="admin_u_name">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary"
onclick="updateDispatcher()">Commit changes</button>
</div>
</div>
</div>
</div>

When pressing the commit changes button (JavaScript):

function updateDispatcher(){
let uname = document.getElementById('admin_u_name').value;
document.getElementById('pass_word').value = '';
let profilePicture = document.getElementById('rep-pic').value;
let oldname = document.getElementById('edit-uname').innerHTML;
let unset = "true";
if(uname.trim() == ''){
if(profilePicture.trim() == ''){
popupInfo('No changes have been made');
$('#editModal').modal('hide');
}else{
uploadProfileAdmin(oldname);
}
}else{
if(profilePicture.trim() != ''){
unset = "false";
}
const uploadChangedData = new XMLHttpRequest();
uploadChangedData.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == 'success'){
uploadProfileAdmin(uname);
}else if(this.responseText == 'nochanges'){
popupInfo("No changes have been made");
$('#editModal').modal('hide');
}else if(this.responseText == 'notauthorized'){
popupWarning("Requirements not meet");
$('#editModal').modal('hide');
}else if(this.responseText == 'error'){
popupError("An error occured updating the profile");
$('#editModal').modal('hide');
}else{
popupError("An error occured updating the profile");
}
console.log(this.responseText);
}
}
126
uploadChangedData.open("POST", "../admin_updating_own_info.php",
true);
uploadChangedData.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
uploadChangedData.send("uname=" + uname + "&unset=" + unset);
}
}

Administrator’s profile photo upload (JavaScript):

function uploadProfileAdmin(name){
if(document.getElementById('rep-pic').value == ''){
popupSuccess("Changes successfull saved");
loadAdminImage();
$('#editModal').modal('hide');
}else{
const formData = new FormData();
const file = fileChoosen.files[0];
formData.append('profile-pic', file, file.name);
formData.append('name', name);
const uploadPhoto = new XMLHttpRequest();
uploadPhoto.open('POST', '../admin_upload_own_photo.php', true);
uploadPhoto.onload = function(){
if(uploadPhoto.status == 200){
if(this.responseText == 'upload'){
popupSuccess("Changes successfully saved");
loadAdminImage();
$('#editModal').modal('hide');
}else if(this.responseText == 'notapic'){
popupWarning("File not supported");
$('#editModal').modal('hide');
}else if(this.responseText == 'fileexist'){
popupWarning("File already exist");
$('#editModal').modal('hide');
}else if(this.responseText == "sizelimit"){
popupWarning("File size exceeds the limit");
$('#editModal').modal('hide');
}else if(this.responseText == "error"){
popupError("Something went wrong");
$('#editModal').modal('hide');
}else{
popupErro("Something went wrong");
$('#editModal').modal('hide');
}
}
}
uploadPhoto.send(formData);
}
}

127
Updating administrator’s profile photo process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
if(isset($_SESSION['authentication'])){
if($_SESSION['authentication']){
unset($_SESSION['authentication']);
try{
require "./db_connection.php";
$proceed = true;
$profile_dir = "./auth_process/images/";
$profile_pic = $profile_dir . basename($_FILES["profile-pic"]
["name"]);
$filetype = strtolower(pathinfo($profile_pic,
PATHINFO_EXTENSION));
$file = $profile_dir . $_POST['name'] . time() . "." .
$filetype;
$file_rename = "images/" . $_POST['name'] . time() . "." .
$filetype;
$uploadok = 0;
$check = getimagesize($_FILES["profile-pic"]["tmp_name"]);
if($check !== false){
$uploadok = 1;
$status = "upload";
}else{
$uploadok = 0;
$status = "notapic";
}
if(file_exists($profile_pic)){
$uploadok = 0;
$status = "fileexist";
}
if($_FILES["profile-pic"]["size"] > 500000){
$uploadok = 0;
$status = "sizelimit";
}
if($uploadok == 0){
echo $status;
}else{
$retrieve_old_file = $connection->prepare("SELECT Profile
FROM admin");
$retrieve_old_file->execute();
$profile = $retrieve_old_file->fetchColumn();
if($profile != ''){
if($profile == "images/adminUserProfile.png"){
$proceed = true;
128
}elseif(file_exists("./auth_process/" . $profile)){
if(!unlink("./auth_process/" . $profile)){
$proceed = false;
}
}else{
$proceed = false;
}
}
if($proceed){
if(move_uploaded_file($_FILES["profile-pic"]["tmp_name"],
$file)){
$save_profile_directory = $connection->prepare("UPDATE
admin SET Profile = :profile");
$save_profile_directory->bindParam(":profile",
$file_rename);
$save_profile_directory->execute();
if($save_profile_directory->rowCount() > 0){

echo $status;
}else{
echo "error";
}
}else{
echo "error";
}
}else{
echo "notallowed";
}
}
}catch(Exception $e){
echo "error";
}

}else{
echo "notauthorized";
}
}else{
echo "notauthorized";
}
?>

Updating administrator’s username process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
129
if(isset($_SESSION['authentication'])){
if($_SESSION['authentication']){
if(isset($_POST['uname']) && !empty(trim($_POST['uname']))){
if($_POST['unset'] == "true"){
unset($_SESSION['authentication']);
}
try{
require "./db_connection.php";
$update_username = $connection->prepare("UPDATE admin SET
Uname = :uname");
$update_username->bindParam(":uname", $_POST['uname']);
$update_username->execute();
if($update_username->rowCount() > 0){
echo "success";
}else{
echo "nochanges";
}
}catch(Exception $e){
echo "error";
}
}
}else{
echo "notauthorized";
}
}else{
echo "notauthorized";
}
?>

7. Resetting administrator’s web-based application

130
When pressing the reset button (JavaScript):

const uploadChangedData = new XMLHttpRequest();


uploadChangedData.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == 'success'){
window.location.replace('../admin_out.php');
}else if(this.responseText == 'fail'){
popupError("Something went wrong");
}else if(this.responseText == 'notauthorized'){
popupWarning("Requirements not meet");
}else if(this.responseText == 'error'){
popupError("Something went wrong");
}else{
popupError("An error occured updating the profile");
}
console.log(this.responseText);
}
}
uploadChangedData.open("POST",
"../resett/admin_reset_the_web_app.php", true);
uploadChangedData.send();

Reset process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
if(isset($_SESSION['authentication'])){
if($_SESSION['authentication']){
try{
require '../db_connection.php';
$password = sha1('admin');
$reset = $connection->prepare("UPDATE admin SET Uname =
'admin', Password = '$password', Profile =
'images/adminUserProfile.png'");
$reset->execute();
if($reset->rowCount() > 0){
echo "success";
}else{
echo "fail";
}
}catch(Exception $e){
echo "error";
}

131
}else{
echo "notauthorized";
}
}else{
echo "notauthorized";
}
?>

8. Log out

Upon pressing the log out button (JavaScript):

function exit(){
window.location.replace('../admin_out.php');
}

Log out process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}else{
session_destroy();
header('Location: ./');
}
}
else{
header('Location: ./');
}
?>

132
9. Adding dispatcher and setting dispatcher status

Adding dispatcher and setting dispatcher status components (HTML):

<section class="col-lg-6">
<div class="content-fluid subfield-3-1">
<div class="card container-fluid card-danger card-
outline">
<div class="card-header">
<h3 class="card-title">Register
Dispatacher</h3>
<div class="card-tools">
<button type="button" class="btn btn-
tool" data-card-widget="collapse" title="Collapse">
<i class="fas fa-minus"></i>
</button>
</div> <!--/.card tools-->
</div>
<div class="card-body">
<div class="form-group">
<span data-toggle="dispatcher-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="f_name">First name</label>
<input type="text" class="form-control"
id="dis_f_name" placeholder="First name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="dispatcher-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>

133
<label for="middle_name">Middle
name</label>
<input type="text" class="form-control"
id="dis_m_name" placeholder="Middle name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="dispatcher-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="last_name">Last name</label>
<input type="text" class="form-control"
id="dis_l_name" placeholder="Last name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="dispatcher-tooltip"
title="Choose a suffix, choose None if dispatcher has no suffix."
class="fas fa-info-circle" style="color: #9edbff;"></span>
<label for="suffix">Suffix</label>
<select id="suffix" class="form-
control">
<option selected
value="">None</option>
<option value="Jr">Jr</option>
<option value="Sr">Sr</option>
<option value="I">I</option>
<option value="II">II</option>
<option value="III">III</option>
<option value="IV">IV</option>
<option value="V">V</option>
</select>
</div>
<div class="form-group">
<span data-toggle="dispatcher-tooltip"
title="Just append the last 10 digits of mobile number." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="contact_number">Mobile
number</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i
class="fas fa-phone"></i> &ensp;+63</span>
</div>
<input type="tel" class="form-control"
maxlength="10" id="dis_c_num" placeholder="Contact #" pattern="[0-9]
{10}">
</div>
</div>
<div class="form-group">
<span data-toggle="dispatcher-tooltip"
title="Select dispatcher's address." class="fas fa-info-circle"
style="color: #9edbff;"></span>
<label
for="contact_number">Address</label>
134
<select id="address" class="form-control">
<option value="">Select Address</option>
<option value="0">Non-Resident</option>
<option value="Brgy.
Airport">Airport</option>
<option value="Brgy.
Alegria">Alegria</option>
<option value="Brgy. Alta Vista">Alta
Vista</option>
<option value="Brgy.
Bagong">Bagong</option>
<option value="Brgy. Bagong
Buhay">Bagong Buhay</option>
<option
value="Bantigue">Bantigue</option>
<option value="Barangay District
1">Barangay District 1</option>
<option value="Barangay District
10">Barangay District 10 </option>
<option value="Barangay District
11">Barangay District 11 </option>
<option value="Barangay District
12">Barangay District 12 </option>
<option value="Barangay District
13">Barangay District 13 </option>
<option value="Barangay District
14">Barangay District 14 </option>
<option value="Barangay District
15">Barangay District 15 </option>
<option value="Barangay District
16">Barangay District 16 </option>
<option value="Barangay District
17">Barangay District 17 </option>
<option value="Barangay District
18">Barangay District 18 </option>
<option value="Barangay District
19">Barangay District 19 </option>
<option value="Barangay District
2">Barangay District 2 </option>
<option value="Barangay District
20">Barangay District 20 </option>
<option value="Barangay District
21">Barangay District 21 </option>
<option value="Barangay District
22">Barangay District 22 </option>
<option value="Barangay District
23">Barangay District 23 </option>
<option value="Barangay District
24">Barangay District 24 </option>
<option value="Barangay District 25
(Malbasag)">Barangay District 25 (Malbasag) </option>
<option value="Barangay District 26
(Isla Verde)">Barangay District 26 (Isla Verde)</option>
<option value="Barangay District
27">Barangay District 27 </option>
135
<option value="Barangay District
28">Barangay District 28 </option>
<option value="Barangay District 29
(Nadongholan)">Barangay District 29 (Nadongholan) </option>
<option value="Barangay District
3">Barangay District 3 </option>
<option value="Barangay District
4">Barangay District 4 </option>
<option value="Barangay District
5">Barangay District 5 </option>
<option value="Barangay District
6">Barangay District 6 </option>
<option value="Barangay District
7">Barangay District 7 </option>
<option value="Barangay District
8">Barangay District 8 </option>
<option value="Barangay District
9">Barangay District 9 </option>
<option value="Brgy.
Batuan">Batuan</option>
<option value="Brgy.
Bayog">Bayog</option>
<option value="Brgy.
Biliboy">Biliboy</option>
<option value="Brgy. Cabaon-an">Cabaon-
an</option>
<option value="Brgy.
Cabingtan">Cabingtan</option>
<option value="Brgy.
Cabulihan">Cabulihan</option>
<option value="Brgy.
Cagbuhangin">Cagbuhangin</option>
<option value="Brgy. Camp Downes">Camp
Downes</option>
<option value="Brgy. Can-adieng">Can-
adieng</option>
<option value="Brgy. Can-untog">Can-
untog</option>
<option value="Brgy.
Catmon">Catmon</option>
<option value="Brgy. Cogon
Combado">Cogon Combado</option>
<option value="Brgy.
Concepcion">Concepcion</option>
<option value="Brgy.
Curva">Curva</option>
<option value="Brgy. Danhug (Lili-
on)">Danhug (Lili-on)</option>
<option value="Brgy.
Dayhagan">Dayhagan</option>
<option value="Brgy.
Dolores">Dolores</option>
<option value="Brgy.
Domonar">Domonar</option>

136
<option value="Brgy. Don Carlos B.
Rivilla Sr. (Boroc)">Don Carlos B. Rivilla Sr. (Boroc)</option>
<option value="Brgy. Don Felipe
Larrazabal">Don Felipe Larrazabal</option>
<option value="Brgy. Don Potenciano
Larrazabal">Don Potenciano Larrazabal</option>
<option value="Brgy. Doña Feliza Z.
Mejia">Doña Feliza Z. Mejia</option>
<option value="Brgy.
Donghol">Donghol</option>
<option value="Brgy.
Esperanza">Esperanza</option>
<option value="Brgy. Gaas">Gaas</option>
<option value="Brgy. Green Valley">Green
Valley</option>
<option value="Brgy. Guintigui-
an">Guintigui-an</option>
<option value="Brgy.
Hibunawon">Hibunawon</option>
<option value="Brgy.
Hugpa">Hugpa</option>
<option value="Brgy. Ipil">Ipil</option>
<option value="Brgy.
Juaton">Juaton</option>
<option value="Brgy.
Kadaohan">Kadaohan</option>
<option value="Brgy. Labrador
(Balion)">Labrador (Balion)</option>
<option value="Brgy. Lake Danao">Lake
Danao</option>
<option value="Brgy. Lao">Lao</option>
<option value="Brgy.
Leondoni">Leondoni</option>
<option value="Brgy.
Libertad">Libertad</option>
<option value="Brgy.
Liberty">Liberty</option>
<option value="Brgy.
Licuma">Licuma</option>
<option value="Brgy.
Liloan">Liloan</option>
<option value="Brgy.
Linao">Linao</option>
<option value="Brgy. Luna">Luna</option>
<option value="Brgy.
Mabato">Mabato</option>
<option value="Brgy.
Mabini">Mabini</option>
<option value="Brgy.
Macabug">Macabug</option>
<option value="Brgy.
Magaswi">Magaswi</option>
<option value="Brgy.
Mahayag">Mahayag</option>

137
<option value="Brgy.
Mahayahay">Mahayahay</option>
<option value="Brgy.
Manlilinao">Manlilinao</option>
<option value="Brgy.
Margen">Margen</option>
<option value="Brgy.
Mas-in">Mas-in</option>
<option value="Brgy. Matica-a">Matica-
a</option>
<option value="Brgy.
Milagro">Milagro</option>
<option value="Brgy.
Monterico">Monterico</option>
<option value="Brgy.
Nasunogan">Nasunogan</option>
<option value="Brgy.
Naungan">Naungan</option>
<option value="Brgy. Nueva
Sociedad">Nueva Sociedad</option>
<option value="Brgy. Nueva Vista">Nueva
Vista</option>
<option value="Brgy.
Patag">Patag</option>
<option value="Brgy.
Punta">Punta</option>
<option value="Brgy. Quezon,
Jr.">Quezon, Jr.</option>
<option value="Brgy. Rufina M. Tan
(Rawis)">Rufina M. Tan (Rawis)</option>
<option value="Brgy. Sabang Bao">Sabang
Bao</option>
<option value="Brgy.
Salvacion">Salvacion</option>
<option value="Brgy. San Antonio">San
Antonio</option>
<option value="Brgy. San Isidro">San
Isidro</option>
<option value="Brgy. San Jose">San
Jose</option>
<option value="Brgy. San Juan">San
Juan</option>
<option value="Brgy. San Pablo
(Simangan)">San Pablo (Simangan)</option>
<option value="Brgy. San Vicente">San
Vicente</option>
<option value="Brgy. Santo Niño">Santo
Niño</option>
<option value="Brgy.
Sumangga">Sumangga</option>
<option value="Brgy.
Tambulilid">Tambulilid</option>
<option value="Brgy.
Tongonan">Tongonan</option>

138
<option value="Brgy.
Valencia">Valencia</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-block btn-primary
font-weight-bold" id="pin-button" onclick="pinGenerator()">GENERATE
PIN</button>
</div>
<div class="form-group">
<span data-toggle="dispatcher-tooltip"
title="Press the generate PIN button above to generate a PIN."
class="fas fa-info-circle" style="color: #9edbff;"></span>
<label for="pin">Generated PIN</label>
<input class="form-control" id="gen-pin"
type="num" maxlength="4" placeholder="PIN" name="dis_pin"
pattern="[0-9]{4}" disabled>
</div>
<div style="display: flex; flex-direction:
column; align-items: center;">
<div>
<span data-toggle="dispatcher-tooltip"
title="Profile picture is optional, you can leave it empty and the
dispatcher will have the default profile picture." class="fas fa-
info-circle" style="color: #9edbff;"></span>
<label>Profile picture <span
style="color: red">(Optional)</span></label>
</div>
<div class="dispatcher-prof-container">
<div>
<img id="actual-pic"
src="./images/adminUserProfile.png">
<div class="front-word"
onclick="openFile()" title="Upload profile picture">
<span class="fas fa-plus"></span>
</div>
<div class="back-element">
<input id="profile-pic" type="file"
accept="image/*">
</div>
</div>
</div>
<button style="margin-top: 5px; border: 0;
background-color: white;" class="btn-link" title='Reset image'
onclick="resetImage()">
<i class="fas fa-undo"></i>
</button>
</div>
</div><!-- /.card-body -->
<div class="card-footer">
<button class="btn btn-block btn-warning
font-weight-bold" id="dispatcher-submit-button"
onclick="registerDispatcher()">Register Dispatcher</button>
</div>
</div> <!-- /.card -->
139
</div>
</section>

When pressing the register dispatcher button (JavaScript):

function registerDispatcher(){
let contactNumber = document.getElementById('dis_c_num');
let genPin = document.getElementById('gen-pin');
Loader.open();
if(contactNumber.checkValidity() && genPin.checkValidity()){
let dis_fname = document.getElementById('dis_f_name').value;
let dis_mname = document.getElementById('dis_m_name').value;
let dis_lname = document.getElementById('dis_l_name').value;
let invalid_str = /\d/;
if(invalid_str.test(dis_fname) || invalid_str.test(dis_mname) ||
invalid_str.test(dis_lname)){
Loader.close();
popupWarning('An invalid input was detected, please recheck
all the fields');
}else{
let invalid_char = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;
if(invalid_char.test(dis_fname) ||
invalid_char.test(dis_mname) || invalid_char.test(dis_lname)){
Loader.close();
popupWarning('An invalid input was detected, please recheck
all the fields');
}else{
let dis_cnum = document.getElementById('dis_c_num').value;
let dis_pin = document.getElementById('gen-pin').value;
let dis_suffix = document.getElementById('suffix').value;
let address = document.getElementById('address').value;
const registerDispatch = new XMLHttpRequest();
registerDispatch.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == "registered"){
Loader.close();
popupWarning('Dispatcher already registered');
}else if(this.responseText == "success"){
uploadThePhoto(dis_fname, dis_mname, dis_lname,
dis_suffix);
document.getElementById('dis_f_name').value = "";
document.getElementById('dis_m_name').value = "";
document.getElementById('dis_l_name').value = "";
document.getElementById('dis_c_num').value = "";
document.getElementById('gen-pin').value = "";
document.getElementById('suffix').value = "";
document.getElementById('address').value = "";
choosenFile.value = "";
}else if(this.responseText == "pinexist"){
Loader.close();
popupError('PIN already used, please generate another
one'); }else if(this.responseText == "error"){
Loader.close();
140
popupError('Something went wrong');
}else if(this.responseText == "incomplete"){
Loader.close();
popupWarning('Please fill all the fields');
}else{
Loader.close();
popupError('Something went wrong');
}
}
}
registerDispatch.open("POST",
"../admin_dispatcher_process.php", true);
registerDispatch.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
registerDispatch.send("dis_fname=" + dis_fname.trim() +
"&dis_mname=" + dis_mname.trim() + "&dis_lname=" + dis_lname.trim()
+ "&dis_suffix=" + dis_suffix + "&dis_cnum=" + "0" + dis_cnum +
"&dis_pin=" + dis_pin + "&address=" + address);
}
}
}else{
Loader.close();
popupWarning('An invalid input was detected, please recheck all
the fields');
}
}

Registering dispatcher process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
if((isset($_POST['dis_fname']) && !empty(trim($_POST['dis_fname'])))
&& (isset($_POST['dis_mname']) && !empty(trim($_POST['dis_mname'])))
&& (isset($_POST['dis_lname']) && !
empty(trim($_POST['dis_lname']))) && (isset($_POST['dis_cnum']) && !
empty(trim($_POST['dis_cnum'])))
&& (isset($_POST['dis_pin']) && !empty(trim($_POST['dis_pin'])))
&& (isset($_POST['address']) && trim($_POST['address']) != "")){
try{
require './db_connection.php';
$fname = $_POST['dis_fname'];
$mname = $_POST['dis_mname'];
$lname = $_POST['dis_lname'];
$suffix = $_POST['dis_suffix'];
$address = $_POST['address'];
141
$verify_dispatcher = $connection->prepare("SELECT * FROM
dispatchers WHERE FirstName = :fname AND MiddleName = :mname AND
LastName = :lname AND Suffix = :suffix");
$verify_dispatcher->bindParam(':fname', $fname);
$verify_dispatcher->bindParam(':mname', $mname);
$verify_dispatcher->bindParam(':lname', $lname);
$verify_dispatcher->bindParam(':suffix', $suffix);
$verify_dispatcher->execute();
$count = $verify_dispatcher->fetchColumn();
if($count > 0){
echo "registered";
}else{
$pin = $_POST['dis_pin'];
$check_pin = $connection->prepare("SELECT PIN FROM
dispatchers WHERE PIN = :pin");
$check_pin->bindParam(":pin", $pin);
$check_pin->execute();
$count = $check_pin->fetchColumn();
if($count > 0){
echo "pinexist";
}else{
$contact = $_POST['dis_cnum'];
$register_dispatcher = $connection->prepare("INSERT INTO
dispatchers(FirstName, MiddleName, LastName, Suffix, OnDuty, PIN,
Contact, Address) VALUES(:fname, :mname, :lname, :suffix,
FALSE, :pin, :contact, :address)");
$register_dispatcher->bindParam(':fname', $fname);
$register_dispatcher->bindParam(':mname', $mname);
$register_dispatcher->bindParam(':lname', $lname);
$register_dispatcher->bindParam(':suffix', $suffix);
$register_dispatcher->bindParam(':pin', $pin);
$register_dispatcher->bindParam(':contact', $contact);
$register_dispatcher->bindParam(':address', $address);
$register_dispatcher->execute();
echo "success";
}
}
}catch(Exception $e){
echo "error";
}
}else{
echo "incomplete";
}
$connection = null;
?>

When pressing the dispatcher duty button (JavaScript):

function dutyChange(data){
Loader.open();
const changeDuty = new XMLHttpRequest();
changeDuty.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
142
Loader.close();
if(this.responseText == "true"){
dutyChangeSuccess("Dispatcher is on duty");
retrieveRegisteredDispatcher();
}
else if(this.responseText == "false"){
dutyChangeSuccess("Dispatcher is off duty");
retrieveRegisteredDispatcher();
ws.send(data);
}
else if(this.responseText == "error"){
dutyChangeError('Something went wrong');
}
else{
dutyChangeError('Something went wrong');
}
}
}
changeDuty.open("POST", "../admin_dispatching_process.php", true);
changeDuty.setRequestHeader("Content-type", "application/x-www-
form-urlencoded");
changeDuty.send("data=" + data);
}

Changing dispatcher duty status process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
require './db_connection.php';
try{
$data = $_POST["data"];
$select_dispatcher_query = $connection->prepare("SELECT OnDuty
FROM dispatchers WHERE ID = :id");
$select_dispatcher_query->bindParam(":id", $data);
$select_dispatcher_query->execute();
$result = $select_dispatcher_query->fetchColumn();
if($result == 1){
$update_dispatcher_query = $connection->prepare("UPDATE
dispatchers SET OnDuty = FALSE WHERE ID = :id");
$update_dispatcher_query->bindParam(":id", $data);
$duty = "false";
}else{
$update_dispatcher_query = $connection->prepare("UPDATE
dispatchers SET OnDuty = TRUE WHERE ID = :id");
$update_dispatcher_query->bindParam(":id", $data);
143
$duty = "true";
}
$update_dispatcher_query->execute();
if($update_dispatcher_query->rowCount() > 0){
echo $duty;
}else{
echo "error";
}
}catch(Exception $e){
echo "error";
}
$connection = null;
?>

10. Register and generate PUV QR

Register and generate PUV QR components (HTML code):

<section class="col-lg-7">
<div class="content-fluid subfield-1-1">
<div class="card container-fluid card-danger card-
outline">
<div class="card-header">
<h3 class="card-title">Register PUV</h3>
<div class="card-tools">
<button type="button" class="btn btn-
tool" data-card-widget="collapse" title="Collapse">
<i class="fas fa-minus"></i>
</button>
</div> <!--/.card tools-->
</div>
<!-- /.card-header -->
<div class="card-body">
144
<div class="form-group">
<span data-toggle="puv-tooltip" title="Use
the right format e.g. PUV-123." class="fas fa-info-circle"
style="color: #9edbff;"></span>
<label for="plate_number">Plate
Number</label>
<input type="text" class="form-control"
name="plateno" maxlength="7" id="plate_no" placeholder="Plate #"
pattern="[A-Z]{3}-[0-9]{3}" onkeyup="this.value =
this.value.toUpperCase();">
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Choose the proper route of the PUV." class="fas fa-info-
circle" style="color: #9edbff;"></span>
<label for="route">Route</label>
<select name="route" id="rt" class="form-
control">
<option value="">Select route</option>
<option value="albuera">Ormoc -
Albuera</option>
<option value="puertobello">Ormoc -
Puertobello</option>
<option value="sabangbao">Ormoc -
Sabang-Bao</option>
<option value="valencia">Ormoc -
Valencia</option>
</select>
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Enter the right PUV capacity (allowed input is 1 to 2 digits
only, not exceeding the value of 50)" class="fas fa-info-circle"
style="color: #9edbff;"></span>
<label for="puv">PUV Capacity</label>
<input type="number" max="50" id="cpcty"
class="form-control" placeholder="Enter PUV capacity" pattern="[0-9]
{10}">
</div>

<div class="container" style="border: 1px


solid #D5D8DC; border-radius: 5px; background-color: #F8F9F9;">
<br>
<label><sup>Operator's
Information</sup></label>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="first_name">First
Name</label>
<input type="text" class="form-control"
name="fname" id="f_name" placeholder="First name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
145
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="middle_name">Middle
Name</label>
<input type="text" class="form-control"
name="mname" id="m_name" placeholder="Middle name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="last_name">Last Name</label>
<input type="text" class="form-control"
name="lname" id="l_name" placeholder="Last name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Choose a suffix, choose None if operator has no suffix."
class="fas fa-info-circle" style="color: #9edbff;"></span>
<label for="suffix">Suffix</label>
<select id="suffix" class="form-
control">
<option selected
value="">None</option>
<option value="Jr">Jr</option>
<option value="Sr">Sr</option>
<option value="I">I</option>
<option value="II">II</option>
<option value="III">III</option>
<option value="IV">IV</option>
<option value="V">V</option>
</select>
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Just append the last 10 digits of mobile number." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="contact_number">Mobile
Number</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i
class="fas fa-phone"></i> &ensp;+63</span>
</div>
<input type="tel" class="form-control"
name="cnum" id="c_num" placeholder="Contact #" maxlength="10"
pattern="[0-9]{10}">
</div>
</div>
<div class="form-group">

146
<span data-toggle="puv-tooltip"
title="Select operator's address." class="fas fa-info-circle"
style="color: #9edbff;"></span>
<label
for="contact_number">Address</label>
<select id="address" class="form-
control">
<option value="">Select
Address</option>
<option
value="0">Non-Resident</option>
<option value="Brgy.
Airport">Airport</option>
<option value="Brgy.
Alegria">Alegria</option>
<option value="Brgy. Alta Vista">Alta
Vista</option>
<option value="Brgy.
Bagong">Bagong</option>
<option value="Brgy. Bagong
Buhay">Bagong Buhay</option>
<option
value="Bantigue">Bantigue</option>
<option value="Barangay District
1">Barangay District 1</option>
<option value="Barangay District
10">Barangay District 10 </option>
<option value="Barangay District
11">Barangay District 11 </option>
<option value="Barangay District
12">Barangay District 12 </option>
<option value="Barangay District
13">Barangay District 13 </option>
<option value="Barangay District
14">Barangay District 14 </option>
<option value="Barangay District
15">Barangay District 15 </option>
<option value="Barangay District
16">Barangay District 16 </option>
<option value="Barangay District
17">Barangay District 17 </option>
<option value="Barangay District
18">Barangay District 18 </option>
<option value="Barangay District
19">Barangay District 19 </option>
<option value="Barangay District
2">Barangay District 2 </option>
<option value="Barangay District
20">Barangay District 20 </option>
<option value="Barangay District
21">Barangay District 21 </option>
<option value="Barangay District
22">Barangay District 22 </option>
<option value="Barangay District
23">Barangay District 23 </option>
147
<option value="Barangay District
24">Barangay District 24 </option>
<option value="Barangay District 25
(Malbasag)">Barangay District 25 (Malbasag) </option>
<option value="Barangay District 26
(Isla Verde)">Barangay District 26 (Isla Verde)</option>
<option value="Barangay District
27">Barangay District 27 </option>
<option value="Barangay District
28">Barangay District 28 </option>
<option value="Barangay District 29
(Nadongholan)">Barangay District 29 (Nadongholan) </option>
<option value="Barangay District
3">Barangay District 3 </option>
<option value="Barangay District
4">Barangay District 4 </option>
<option value="Barangay District
5">Barangay District 5 </option>
<option value="Barangay District
6">Barangay District 6 </option>
<option value="Barangay District
7">Barangay District 7 </option>
<option value="Barangay District
8">Barangay District 8 </option>
<option value="Barangay District
9">Barangay District 9 </option>
<option value="Brgy.
Batuan">Batuan</option>
<option value="Brgy.
Bayog">Bayog</option>
<option value="Brgy.
Biliboy">Biliboy</option>
<option value="Brgy. Cabaon-
an">Cabaon-an</option>
<option value="Brgy.
Cabingtan">Cabingtan</option>
<option value="Brgy.
Cabulihan">Cabulihan</option>
<option value="Brgy.
Cagbuhangin">Cagbuhangin</option>
<option value="Brgy. Camp Downes">Camp
Downes</option>
<option value="Brgy. Can-adieng">Can-
adieng</option>
<option value="Brgy. Can-untog">Can-
untog</option>
<option value="Brgy.
Catmon">Catmon</option>
<option value="Brgy. Cogon
Combado">Cogon Combado</option>
<option value="Brgy.
Concepcion">Concepcion</option>
<option value="Brgy.
Curva">Curva</option>

148
<option value="Brgy. Danhug (Lili-
on)">Danhug (Lili-on)</option>
<option value="Brgy.
Dayhagan">Dayhagan</option>
<option value="Brgy.
Dolores">Dolores</option>
<option value="Brgy.
Domonar">Domonar</option>
<option value="Brgy. Don Carlos B.
Rivilla Sr. (Boroc)">Don Carlos B. Rivilla Sr. (Boroc)</option>
<option value="Brgy. Don Felipe
Larrazabal">Don Felipe Larrazabal</option>
<option value="Brgy. Don Potenciano
Larrazabal">Don Potenciano Larrazabal</option>
<option value="Brgy. Doña Feliza Z.
Mejia">Doña Feliza Z. Mejia</option>
<option value="Brgy.
Donghol">Donghol</option>
<option value="Brgy.
Esperanza">Esperanza</option>
<option value="Brgy.
Gaas">Gaas</option>
<option value="Brgy. Green
Valley">Green Valley</option>
<option value="Brgy. Guintigui-
an">Guintigui-an</option>
<option value="Brgy.
Hibunawon">Hibunawon</option>
<option value="Brgy.
Hugpa">Hugpa</option>
<option value="Brgy.
Ipil">Ipil</option>
<option value="Brgy.
Juaton">Juaton</option>
<option value="Brgy.
Kadaohan">Kadaohan</option>
<option value="Brgy. Labrador
(Balion)">Labrador (Balion)</option>
<option value="Brgy. Lake Danao">Lake
Danao</option>
<option value="Brgy. Lao">Lao</option>
<option value="Brgy.
Leondoni">Leondoni</option>
<option value="Brgy.
Libertad">Libertad</option>
<option value="Brgy.
Liberty">Liberty</option>
<option value="Brgy.
Licuma">Licuma</option>
<option value="Brgy.
Liloan">Liloan</option>
<option value="Brgy.
Linao">Linao</option>
<option value="Brgy.
Luna">Luna</option>
149
<option value="Brgy.
Mabato">Mabato</option>
<option value="Brgy.
Mabini">Mabini</option>
<option value="Brgy.
Macabug">Macabug</option>
<option value="Brgy.
Magaswi">Magaswi</option>
<option value="Brgy.
Mahayag">Mahayag</option>
<option value="Brgy.
Mahayahay">Mahayahay</option>
<option value="Brgy.
Manlilinao">Manlilinao</option>
<option value="Brgy.
Margen">Margen</option>
<option value="Brgy.
Mas-in">Mas-in</option>
<option value="Brgy. Matica-a">Matica-
a</option>
<option value="Brgy.
Milagro">Milagro</option>
<option value="Brgy.
Monterico">Monterico</option>
<option value="Brgy.
Nasunogan">Nasunogan</option>
<option value="Brgy.
Naungan">Naungan</option>
<option value="Brgy. Nueva
Sociedad">Nueva Sociedad</option>
<option value="Brgy. Nueva
Vista">Nueva Vista</option>
<option value="Brgy.
Patag">Patag</option>
<option value="Brgy.
Punta">Punta</option>
<option value="Brgy. Quezon,
Jr.">Quezon, Jr.</option>
<option value="Brgy. Rufina M. Tan
(Rawis)">Rufina M. Tan (Rawis)</option>
<option value="Brgy. Sabang
Bao">Sabang Bao</option>
<option value="Brgy.
Salvacion">Salvacion</option>
<option value="Brgy. San Antonio">San
Antonio</option>
<option value="Brgy. San Isidro">San
Isidro</option>
<option value="Brgy. San Jose">San
Jose</option>
<option value="Brgy. San Juan">San
Juan</option>
<option value="Brgy. San Pablo
(Simangan)">San Pablo (Simangan)</option>

150
<option value="Brgy. San Vicente">San
Vicente</option>
<option value="Brgy. Santo Niño">Santo
Niño</option>
<option value="Brgy.
Sumangga">Sumangga</option>
<option value="Brgy.
Tambulilid">Tambulilid</option>
<option value="Brgy.
Tongonan">Tongonan</option>
<option value="Brgy.
Valencia">Valencia</option>
</select>
</div>
</div>
<br>
<div class="container" style="border: 1px
solid #D5D8DC; border-radius: 5px; background-color: #F8F9F9;">
<br>
<label><sup>Driver's
Information</sup></label>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="first_name">First
Name</label>
<input type="text" class="form-control"
name="fname" id="df_name" placeholder="First name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="middle_name">Middle
Name</label>
<input type="text" class="form-control"
name="mname" id="dm_name" placeholder="Middle name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Numbers and special characters are not accepted." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="last_name">Last Name</label>
<input type="text" class="form-control"
name="lname" id="dl_name" placeholder="Last name" maxlength="40"
onfocusout="this.value = makeItCorrect(this.value)">
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Choose a suffix, choose None if operator has no suffix."
class="fas fa-info-circle" style="color: #9edbff;"></span>
<label for="suffix">Suffix</label>
151
<select id="dsuffix" class="form-
control">
<option selected
value="">None</option>
<option value="Jr">Jr</option>
<option value="Sr">Sr</option>
<option value="I">I</option>
<option value="II">II</option>
<option value="III">III</option>
<option value="IV">IV</option>
<option value="V">V</option>
</select>
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Just append the last 10 digits of mobile number." class="fas
fa-info-circle" style="color: #9edbff;"></span>
<label for="contact_number">Mobile
Number</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i
class="fas fa-phone"></i> &ensp;+63</span>
</div>
<input type="tel" class="form-control"
name="cnum" id="dc_num" placeholder="Contact #" maxlength="10"
pattern="[0-9]{10}">
</div>
</div>
<div class="form-group">
<span data-toggle="puv-tooltip"
title="Select driver's address." class="fas fa-info-circle"
style="color: #9edbff;"></span>
<label
for="contact_number">Address</label>
<select id="daddress" class="form-
control">
<option value="">Select
Address</option>
<option
value="0">Non-Resident</option>
<option value="Brgy.
Airport">Airport</option>
<option value="Brgy.
Alegria">Alegria</option>
<option value="Brgy. Alta Vista">Alta
Vista</option>
<option value="Brgy.
Bagong">Bagong</option>
<option value="Brgy. Bagong
Buhay">Bagong Buhay</option>
<option
value="Bantigue">Bantigue</option>
<option value="Barangay District
1">Barangay District 1</option>
152
<option value="Barangay District
10">Barangay District 10 </option>
<option value="Barangay District
11">Barangay District 11 </option>
<option value="Barangay District
12">Barangay District 12 </option>
<option value="Barangay District
13">Barangay District 13 </option>
<option value="Barangay District
14">Barangay District 14 </option>
<option value="Barangay District
15">Barangay District 15 </option>
<option value="Barangay District
16">Barangay District 16 </option>
<option value="Barangay District
17">Barangay District 17 </option>
<option value="Barangay District
18">Barangay District 18 </option>
<option value="Barangay District
19">Barangay District 19 </option>
<option value="Barangay District
2">Barangay District 2 </option>
<option value="Barangay District
20">Barangay District 20 </option>
<option value="Barangay District
21">Barangay District 21 </option>
<option value="Barangay District
22">Barangay District 22 </option>
<option value="Barangay District
23">Barangay District 23 </option>
<option value="Barangay District
24">Barangay District 24 </option>
<option value="Barangay District 25
(Malbasag)">Barangay District 25 (Malbasag) </option>
<option value="Barangay District 26
(Isla Verde)">Barangay District 26 (Isla Verde)</option>
<option value="Barangay District
27">Barangay District 27 </option>
<option value="Barangay District
28">Barangay District 28 </option>
<option value="Barangay District 29
(Nadongholan)">Barangay District 29 (Nadongholan) </option>
<option value="Barangay District
3">Barangay District 3 </option>
<option value="Barangay District
4">Barangay District 4 </option>
<option value="Barangay District
5">Barangay District 5 </option>
<option value="Barangay District
6">Barangay District 6 </option>
<option value="Barangay District
7">Barangay District 7 </option>
<option value="Barangay District
8">Barangay District 8 </option>

153
<option value="Barangay District
9">Barangay District 9 </option>
<option value="Brgy.
Batuan">Batuan</option>
<option value="Brgy.
Bayog">Bayog</option>
<option value="Brgy.
Biliboy">Biliboy</option>
<option value="Brgy. Cabaon-
an">Cabaon-an</option>
<option value="Brgy.
Cabingtan">Cabingtan</option>
<option value="Brgy.
Cabulihan">Cabulihan</option>
<option value="Brgy.
Cagbuhangin">Cagbuhangin</option>
<option value="Brgy. Camp Downes">Camp
Downes</option>
<option value="Brgy. Can-adieng">Can-
adieng</option>
<option value="Brgy. Can-untog">Can-
untog</option>
<option value="Brgy.
Catmon">Catmon</option>
<option value="Brgy. Cogon
Combado">Cogon Combado</option>
<option value="Brgy.
Concepcion">Concepcion</option>
<option value="Brgy.
Curva">Curva</option>
<option value="Brgy. Danhug (Lili-
on)">Danhug (Lili-on)</option>
<option value="Brgy.
Dayhagan">Dayhagan</option>
<option value="Brgy.
Dolores">Dolores</option>
<option value="Brgy.
Domonar">Domonar</option>
<option value="Brgy. Don Carlos B.
Rivilla Sr. (Boroc)">Don Carlos B. Rivilla Sr. (Boroc)</option>
<option value="Brgy. Don Felipe
Larrazabal">Don Felipe Larrazabal</option>
<option value="Brgy. Don Potenciano
Larrazabal">Don Potenciano Larrazabal</option>
<option value="Brgy. Doña Feliza Z.
Mejia">Doña Feliza Z. Mejia</option>
<option value="Brgy.
Donghol">Donghol</option>
<option value="Brgy.
Esperanza">Esperanza</option>
<option value="Brgy.
Gaas">Gaas</option>
<option value="Brgy. Green
Valley">Green Valley</option>

154
<option value="Brgy. Guintigui-
an">Guintigui-an</option>
<option value="Brgy.
Hibunawon">Hibunawon</option>
<option value="Brgy.
Hugpa">Hugpa</option>
<option value="Brgy.
Ipil">Ipil</option>
<option value="Brgy.
Juaton">Juaton</option>
<option value="Brgy.
Kadaohan">Kadaohan</option>
<option value="Brgy. Labrador
(Balion)">Labrador (Balion)</option>
<option value="Brgy. Lake Danao">Lake
Danao</option>
<option value="Brgy. Lao">Lao</option>
<option value="Brgy.
Leondoni">Leondoni</option>
<option value="Brgy.
Libertad">Libertad</option>
<option value="Brgy.
Liberty">Liberty</option>
<option value="Brgy.
Licuma">Licuma</option>
<option value="Brgy.
Liloan">Liloan</option>
<option value="Brgy.
Linao">Linao</option>
<option value="Brgy.
Luna">Luna</option>
<option value="Brgy.
Mabato">Mabato</option>
<option value="Brgy.
Mabini">Mabini</option>
<option value="Brgy.
Macabug">Macabug</option>
<option value="Brgy.
Magaswi">Magaswi</option>
<option value="Brgy.
Mahayag">Mahayag</option>
<option value="Brgy.
Mahayahay">Mahayahay</option>
<option value="Brgy.
Manlilinao">Manlilinao</option>
<option value="Brgy.
Margen">Margen</option>
<option value="Brgy.
Mas-in">Mas-in</option>
<option value="Brgy. Matica-a">Matica-
a</option>
<option value="Brgy.
Milagro">Milagro</option>
<option value="Brgy.
Monterico">Monterico</option>
155
<option value="Brgy.
Nasunogan">Nasunogan</option>
<option value="Brgy.
Naungan">Naungan</option>
<option value="Brgy. Nueva
Sociedad">Nueva Sociedad</option>
<option value="Brgy. Nueva
Vista">Nueva Vista</option>
<option value="Brgy.
Patag">Patag</option>
<option value="Brgy.
Punta">Punta</option>
<option value="Brgy. Quezon,
Jr.">Quezon, Jr.</option>
<option value="Brgy. Rufina M. Tan
(Rawis)">Rufina M. Tan (Rawis)</option>
<option value="Brgy. Sabang
Bao">Sabang Bao</option>
<option value="Brgy.
Salvacion">Salvacion</option>
<option value="Brgy. San Antonio">San
Antonio</option>
<option value="Brgy. San Isidro">San
Isidro</option>
<option value="Brgy. San Jose">San
Jose</option>
<option value="Brgy. San Juan">San
Juan</option>
<option value="Brgy. San Pablo
(Simangan)">San Pablo (Simangan)</option>
<option value="Brgy. San Vicente">San
Vicente</option>
<option value="Brgy. Santo Niño">Santo
Niño</option>
<option value="Brgy.
Sumangga">Sumangga</option>
<option value="Brgy.
Tambulilid">Tambulilid</option>
<option value="Brgy.
Tongonan">Tongonan</option>
<option value="Brgy.
Valencia">Valencia</option>
</select>
</div>
</div>
<br>
<div style="display: flex; flex-direction:
column; align-items: center;">
<div>
<span data-toggle="puv-tooltip"
title="Vehicle image is optional, you can leave it empty and the
vehicle will have the default vehicle image." class="fas fa-info-
circle" style="color: #9edbff;"></span>
<label>Vehicle image <span style="color:
red">(Optional)</span></label>
156
</div>
<div class="vehicle-prof-container">
<div>
<img id="actual-pic"
src="../vehicle_images/vehicleImage.png">
<div class="vehicle-front-word"
onclick="openFile()" title="Upload vehicle image">
<span class="fas fa-plus"></span>
</div>
<div class="back-element">
<input id="profile-pic" type="file"
accept="image/*">
</div>
</div>
</div>
<div style="margin-top: 10px;">
<button style="border: 0; background-
color: white;" class="btn-link" title='Reset image'
onclick="resetImage()">
<i class="fas fa-undo"></i>
</button>
</div>
</div>
</div><!-- /.card-body -->
<div class="card-footer">
<button class="btn btn-block btn-warning
font-weight-bold" id="vehicle-submit-button" type="button"
onclick="registerVehicle()">Register Vehicle</button>
</div>
</div> <!-- /.card -->
</div> <!-- /.content-fluid x subfield-1-1 -->
</section>

When pressing register vehicle (JavaScript):

function registerVehicle(){
let contactNumber = document.getElementById('c_num');
let plateNumber = document.getElementById('plate_no');
Loader.open();
if(contactNumber.checkValidity() && plateNumber.checkValidity()){
let f_name = document.getElementById('f_name').value;
let m_name = document.getElementById('m_name').value;
let l_name = document.getElementById('l_name').value;
let df_name = document.getElementById('df_name').value;
let dm_name = document.getElementById('dm_name').value;
let dl_name = document.getElementById('dl_name').value;
let invalid_str = /\d/;
if(invalid_str.test(f_name) || invalid_str.test(m_name) ||
invalid_str.test(l_name) || invalid_str.test(df_name) ||
invalid_str.test(dm_name) || invalid_str.test(dl_name)){
Loader.close();
popupWarning('Numbers are not allowed in names');
}else{
157
let invalid_char = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;
if(invalid_char.test(f_name) || invalid_char.test(m_name) ||
invalid_char.test(l_name) || invalid_char.test(df_name) ||
invalid_char.test(dm_name) || invalid_char.test(dl_name)){
Loader.close();
popupWarning('Special characters are not allowed in names');
}else{
let suffix = document.getElementById('suffix').value;
let dsuffix = document.getElementById('dsuffix').value;
let c_num = document.getElementById('c_num').value;
let dc_num = document.getElementById('dc_num').value;
let address = document.getElementById('address').value;
let daddress = document.getElementById('daddress').value;
let plate_no = document.getElementById('plate_no').value;
let rt = document.getElementById('rt').value;
let cpcty = document.getElementById('cpcty').value;
if(cpcty > 50 || cpcty < 0){
Loader.close();
popupWarning('Capacity exceeds the limitations');
}else{
parameter = plate_no + '_' + rt;
const registerPUV = new XMLHttpRequest();
registerPUV.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
Loader.close();
if(this.responseText == "registered"){
popupInfo('Vehicle Already Registered!');
}
else if(this.responseText == "error"){
popupError('Something went wrong');
}
else if(this.responseText == "incomplete"){
popupWarning('Please fill all the fields');
}
else if(this.responseText == plate_no){
uploadThePhoto(plate_no);
document.getElementById('vehicle-qrimage').src =
'../qrs/' + this.responseText + '.png'; //used
document.getElementById('vehicle-plateno').innerHTML
= this.responseText;
document.getElementById('f_name').value = '';
document.getElementById('m_name').value = '';
document.getElementById('l_name').value = '';
document.getElementById('c_num').value = '';
document.getElementById('address').value = '';
document.getElementById('df_name').value = '';
document.getElementById('dm_name').value = '';
document.getElementById('dl_name').value = '';
document.getElementById('dc_num').value = '';
document.getElementById('daddress').value = '';
document.getElementById('plate_no').value = '';
document.getElementById('rt').value = '';
document.getElementById('cpcty').value = '';
document.getElementById('suffix').value = '';
document.getElementById('dsuffix').value = '';
158
}
else{
popupError('Something went wrong');
}
console.log(this.responseText);
}
};
registerPUV.open("POST",
"../admin_registering_vehicle_process.php", true);
registerPUV.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
registerPUV.send("fname=" + f_name.trim() + "&mname=" +
m_name.trim() + "&lname=" + l_name.trim() + "&suffix=" + suffix +
"&cnum=0"
+ c_num + "&plateno=" + plate_no +
"&route=" + rt + "&capacity=" + cpcty + "&address=" + address +
"&dfname=" + df_name.trim()
+ "&dmname=" + dm_name.trim() +
"&dlname=" + dl_name.trim() + "&dsuffix=" + dsuffix + "&dcnum=0" +
dc_num + "&daddress=" + daddress);
}
}
}
}else{
Loader.close();
popupWarning('Invalid input, please recheck all the fields');
}
}

Registering vehicle process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
include('./phpqrcode/qrlib.php');

function infoCrypt($plaintext){
$key = "udWH+XfEbKB44oqM";

$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key,
$options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key,
$as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
159
return $ciphertext;
}

if((isset($_POST['fname']) && !empty(trim($_POST['fname']))) &&


(isset($_POST['mname']) && !empty(trim($_POST['mname'])))
&& (isset($_POST['lname']) && !empty(trim($_POST['lname']))) &&
(isset($_POST['cnum']) && !empty(trim($_POST['cnum'])))
&& (isset($_POST['plateno']) && !empty(trim($_POST['plateno'])))
&& (isset($_POST['route']) && !empty(trim($_POST['route'])))
&& (isset($_POST['capacity']) && !empty(trim($_POST['capacity'])))
&& (isset($_POST['dfname']) && !empty(trim($_POST['dfname']))) &&
(isset($_POST['dmname']) && !empty(trim($_POST['dmname'])))
&& (isset($_POST['dlname']) && !empty(trim($_POST['dlname']))) &&
(isset($_POST['dcnum']) && !empty(trim($_POST['dcnum']))) &&
(isset($_POST['address']) && trim($_POST['address']) != "")
&& (isset($_POST['daddress']) && trim($_POST['daddress']) != "")){

$plateno = $_POST['plateno'];
$route = $_POST['route'];
$capacity = (int)$_POST['capacity'];

try{
require 'db_connection.php';
$checkplateno = $connection->prepare("SELECT COUNT(*) as Count,
Status FROM registered_vehicles WHERE PlateNo = :plateno");
$checkplateno->bindParam(':plateno', $plateno);
$checkplateno->execute();
$row_count = $checkplateno->fetch();

$contact = $_POST['cnum'];
$vehicle_info = array("type" => "vehicle", "plateno" =>
$plateno);
$vehicle_capacity = array();
if($row_count['Count'] > 0){
if($row_count['Status'] == 'Deleted'){
for($count = 1; $count <= $capacity; $count++){
array_push($vehicle_capacity, array("Name" => "",
"Companion" => ""));
}
$full_capacity = json_encode($vehicle_capacity);
$register_vehicle = $connection->prepare("UPDATE
registered_vehicles SET FirstName = :firstname, MiddleName
= :middlename, LastName = :lastname, Suffix = :suffix, Address
= :address, Route = :route, Capacity = :capacity,
Contact = :contact,
DFirstName = :dfname, DMiddleName = :dmname, DLastName = :dlname,
DSuffix = :dsuffix, DContact = :dcontact, DAddress = :daddress,
Status = 'Active' WHERE PlateNo = :plateno");
$register_vehicle->bindParam(':firstname', $_POST['fname']);
$register_vehicle->bindParam(':middlename',
$_POST['mname']);
$register_vehicle->bindParam(':lastname', $_POST['lname']);
$register_vehicle->bindParam(':suffix', $_POST['suffix']);
$register_vehicle->bindParam(':plateno', $plateno);
160
$register_vehicle->bindParam(':route', $route);
$register_vehicle->bindParam(':capacity', $capacity);
$register_vehicle->bindParam(':contact', $contact);
$register_vehicle->bindParam(':dfname', $_POST['dfname']);
$register_vehicle->bindParam(':dmname', $_POST['dmname']);
$register_vehicle->bindParam(':dlname', $_POST['dlname']);
$register_vehicle->bindParam(':dsuffix', $_POST['dsuffix']);
$register_vehicle->bindParam(':dcontact', $_POST['dcnum']);
$register_vehicle->bindParam(':daddress',
$_POST['daddress']);
$register_vehicle->bindParam(':address', $_POST['address']);
$register_vehicle->execute();
$is_success = $register_vehicle->rowCount();
if($is_success > 0){
$driver = $_POST['dfname'] . ' ' . $_POST['dmname'] . '
' . $_POST['dlname'] . ' ' . $_POST['dsuffix'];
$name = $_POST['fname'] . ' ' . $_POST['mname'] . ' ' .
$_POST['lname'] . ' ' . $_POST['suffix'];
$data = array("vehicle" => $_POST['plateno'], "operator"
=> $name, "driver" => $driver, "contact_num" => $_POST['cnum'],
"route" => $_POST['route'], "capacity" => $capacity, "queuing" =>
false, "returning" => false);
$vehicles_json =
file_get_contents('./vehicles/vehicles.json');
$vehicles_data = json_decode($vehicles_json, true);
array_push($vehicles_data, $data);
$data_json = json_encode($vehicles_data);
$vehicles_file = fopen('./vehicles/vehicles.json', 'w');
$vehicle_name = fopen('./vehicles/' . $route . '_' .
$plateno . '.json', 'w');
fwrite($vehicles_file, $data_json);
fwrite($vehicle_name, $full_capacity);
fclose($vehicles_file);
fclose($vehicle_name);
QRcode::png(infoCrypt(json_encode($vehicle_info)),
'./qrs/' . $_POST['plateno'] . '.png', QR_ECLEVEL_L, 4);
echo $_POST['plateno'];
}else{
echo "error";
}
}else{
echo "registered";
}
}else{
for($count = 1; $count <= $capacity; $count++){
array_push($vehicle_capacity, array("Name" => "",
"Companion" => "", "Number" => ""));
}
$full_capacity = json_encode($vehicle_capacity);
$register_vehicle = $connection->prepare("INSERT INTO
registered_vehicles(FirstName, MiddleName, LastName, Suffix,
Address, PlateNo, Route, Capacity, Contact, DFirstName, DMiddleName,
DLastName, DSuffix, DContact, DAddress, Status)
VALUES(:firstname,
:middlename, :lastname, :suffix, :address, :plateno, :route, :capaci
161
ty, :contact, :dfname, :dmname, :dlname, :dsuffix, :dcontact, :daddr
ess, 'Active')");
$register_vehicle->bindParam(':firstname', $_POST['fname']);
$register_vehicle->bindParam(':middlename',
$_POST['mname']);
$register_vehicle->bindParam(':lastname', $_POST['lname']);
$register_vehicle->bindParam(':suffix', $_POST['suffix']);
$register_vehicle->bindParam(':plateno', $plateno);
$register_vehicle->bindParam(':route', $route);
$register_vehicle->bindParam(':capacity', $capacity);
$register_vehicle->bindParam(':contact', $contact);
$register_vehicle->bindParam(':dfname', $_POST['dfname']);
$register_vehicle->bindParam(':dmname', $_POST['dmname']);
$register_vehicle->bindParam(':dlname', $_POST['dlname']);
$register_vehicle->bindParam(':dsuffix', $_POST['dsuffix']);
$register_vehicle->bindParam(':dcontact', $_POST['dcnum']);
$register_vehicle->bindParam(':daddress',
$_POST['daddress']);
$register_vehicle->bindParam(':address', $_POST['address']);
$register_vehicle->execute();
$driver = $_POST['dfname'] . ' ' . $_POST['dmname'] . ' ' .
$_POST['dlname'] . ' ' . $_POST['dsuffix'];
$name = $_POST['fname'] . ' ' . $_POST['mname'] . ' ' .
$_POST['lname'] . ' ' . $_POST['suffix'];
$data = array("vehicle" => $_POST['plateno'], "operator" =>
$name, "driver" => $driver, "contact_num" => $_POST['cnum'], "route"
=> $_POST['route'], "capacity" => $capacity, "queuing" => false,
"returning" => false);
$vehicles_json =
file_get_contents('./vehicles/vehicles.json');
$vehicles_data = json_decode($vehicles_json, true);
array_push($vehicles_data, $data);
$data_json = json_encode($vehicles_data);
$vehicles_file = fopen('./vehicles/vehicles.json', 'w');
$vehicle_name = fopen('./vehicles/' . $route . '_' .
$plateno . '.json', 'w');
fwrite($vehicles_file, $data_json);
fwrite($vehicle_name, $full_capacity);
fclose($vehicles_file);
fclose($vehicle_name);
QRcode::png(infoCrypt(json_encode($vehicle_info)),
'./qrs/' . $_POST['plateno'] . '.png', QR_ECLEVEL_L, 4);
echo $_POST['plateno'];
}
}catch(Exception $e){
echo $e;
}
$connection = null;
}
else{
echo "incomplete";

162
11. Queuing PUVs

Queuing PUVs table components (PHP and HTML):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
$data = '';
if(isset($_POST['data'])){
$data = $_POST['data'];
}
$queuing_vehicles =
json_decode(file_get_contents('./vehicles/queuing_vehicles.json'));
echo "<table class='queuing-vehicle-table'>";
echo "<tr class='rvt'>";
echo "<th>Vehicle</th>";
echo "<th>Operator</th>";
echo "<th>Driver</th>";
echo "<th>Route</th>";
echo "<th>Passengers</th>";
echo "<th>Dequeue</th>";
echo "</tr>";
if(sizeof($queuing_vehicles) > 0){
if($data != ''){
foreach($queuing_vehicles as $vehicle){
if($vehicle->route == $data || $vehicle->vehicle == $data){

163
$puv = '"' . $vehicle->vehicle . '"';
if($vehicle->passengers == $vehicle->capacity){
echo "<tr style='background-color: #CD6155; border-top:
1px solid #808B96; color: white'>";
echo "<td>" . $vehicle->vehicle . "</td>";
echo "<td>" . $vehicle->operator . "</td>";
echo "<td>" . $vehicle->driver . "</td>";
echo "<td>" . strtoupper($vehicle->route) . "</td>";
echo "<td>" . $vehicle->passengers . "/" . $vehicle-
>capacity . "</td>";
echo "<td><button class='fas fa-sign-out-alt'
type='button' style='background-color: #F4D03F; width: 30px; height:
20px; padding: 0; border: none; border-radius: 3px; margin-top:
3px;' onclick='unqueueVehicle(" . $puv . ")'></button></td>";
echo "</tr>";
}else{
echo "<tr style='background-color: #2ECC71; border-top:
1px solid #808B96; color: white'>";
echo "<td>" . $vehicle->vehicle . "</td>";
echo "<td>" . $vehicle->operator . "</td>";
echo "<td>" . $vehicle->driver . "</td>";
echo "<td>" . strtoupper($vehicle->route) . "</td>";
echo "<td>" . $vehicle->passengers . "/" . $vehicle-
>capacity . "</td>";
echo "<td><button class='fas fa-sign-out-alt'
type='button' style='background-color: #F4D03F; width: 30px; height:
20px; padding: 0; border: none; border-radius: 3px; margin-top:
3px;' onclick='unqueueVehicle(" . $puv . ")'></button></td>";
echo "</tr>";
}
}
}
}
else{
foreach($queuing_vehicles as $vehicle){
$puv = '"' . $vehicle->vehicle . '"';
if($vehicle->passengers == $vehicle->capacity){
echo "<tr style='background-color: #CD6155; border-top:
1px solid #808B96; color: white'>";
echo "<td>" . $vehicle->vehicle . "</td>";
echo "<td>" . $vehicle->operator . "</td>";
echo "<td>" . $vehicle->driver . "</td>";
echo "<td>" . strtoupper($vehicle->route) . "</td>";
echo "<td>" . $vehicle->passengers . "/" . $vehicle-
>capacity . "</td>";
echo "<td><button class='fas fa-sign-out-alt'
type='button' style='background-color: #F4D03F; width: 30px; height:
20px; padding: 0; border: none; border-radius: 3px; margin-top:
3px;' onclick='unqueueVehicle(" . $puv . ")'></button></td>";
echo "</tr>";
}else{
echo "<tr style='background-color: #2ECC71; border-top:
1px solid #808B96; color: white'>";
echo "<td>" . $vehicle->vehicle . "</td>";
echo "<td>" . $vehicle->operator . "</td>";
164
echo "<td>" . $vehicle->driver . "</td>";
echo "<td>" . strtoupper($vehicle->route) . "</td>";
echo "<td>" . $vehicle->passengers . "/" . $vehicle-
>capacity . "</td>";
echo "<td><button class='fas fa-sign-out-alt'
type='button' style='background-color: #F4D03F; width: 30px; height:
20px; padding: 0; border: none; border-radius: 3px; margin-top:
3px;' onclick='unqueueVehicle(" . $puv . ")'></button></td>";
echo "</tr>";
}
}
}
}
else{
echo "<tr><td colspan='6'>No queuing vehicles</td></tr>";
}
echo "</table>";
?>

Server request and reply handle for queuing PUVs (JavaScript):

function loadQueuingVehicles(){
if(document.getElementById('search-input').value != ''){
let searchedDestination = document.getElementById('search-
input').value;
const queuingVehicles = new XMLHttpRequest();
queuingVehicles.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-6-1-sub').innerHTML =
this.responseText;
}
};
queuingVehicles.open("POST",
"../admin_queuing_vehicles_list.php", true);
queuingVehicles.setRequestHeader("Content-type", "application/x-
www-form-urlencoded");
queuingVehicles.send("data=" + searchedDestination);
}else if(document.getElementById('searched-destination').value !=
''){
let searchedDestination = document.getElementById('searched-
destination').value;
const queuingVehicles = new XMLHttpRequest();
queuingVehicles.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-6-1-sub').innerHTML =
this.responseText;
}
};
queuingVehicles.open("POST",
"../admin_queuing_vehicles_list.php", true);
queuingVehicles.setRequestHeader("Content-type", "application/x-
www-form-urlencoded");
queuingVehicles.send("data=" + searchedDestination);
165
}else{
const queuingVehicles = new XMLHttpRequest();
queuingVehicles.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-6-1-sub').innerHTML =
this.responseText;
}
};
queuingVehicles.open("POST",
"../admin_queuing_vehicles_list.php", true);
queuingVehicles.send();
}
}

Loop server request and reply handle for queuing PUVs (JavaScript):

setInterval(function(){
loadQueuingVehicles();
}, 1500);

When pressing the dequeue button (JavaScript):

function unqueueVehicle(data){
Swal.fire({
title: 'Are you sure you want to remove ' + data + ' in queuing
list?',
showCancelButton: true,
confirmButtonText: 'Dequeue',
}).then((result) => {
if(result.isConfirmed){
const unqueuePUV = new XMLHttpRequest();
unqueuePUV.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == "success"){
popupSuccess('Vehicle is successfully unqueued');
}
else if(this.responseText == "error"){
popupError('Something went wrong');
}
else{
popupError('Something went wrong');
}
console.log(this.responseText);
}
};
unqueuePUV.open("POST", "../admin_unqueue_vehicle.php", true);
unqueuePUV.setRequestHeader("Content-type", "application/x-
www-form-urlencoded");
unqueuePUV.send("data=" + data);
}else if (result.isDenied){
Swal.fire('Nothing has been done.', '', 'info');

166
}
})
}

Dequeue process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
require './db_connection.php';
$data = $_POST['data'];
$proceed = true;
try{
$delete_passenger_query = $connection->prepare("DELETE FROM
loaded_passengers WHERE Vehicle = :vehicle");
$delete_passenger_query->bindParam(":vehicle", $data);
$delete_passenger_query->execute();
}catch(Exception $e){
$proceed = false;
}
if($proceed){
$queuing_vehicles_list =
json_decode(file_get_contents('./vehicles/queuing_vehicles.json'));
$count_1 = 0;
$count_2 = 0;
$count_3 = 0;
if(sizeof($queuing_vehicles_list) > 0){
foreach($queuing_vehicles_list as $vehicle){
if($vehicle->vehicle == $data){
$queue_time = $vehicle->time_queue;
array_splice($queuing_vehicles_list, $count_1, 1);
$vehicles_list =
json_decode(file_get_contents('./vehicles/vehicles.json'));
foreach($vehicles_list as $list_of_vehicles){
if($list_of_vehicles->vehicle === $data &&
$list_of_vehicles->queuing === true){
$puv_passengers = $list_of_vehicles->route . "_" .
$list_of_vehicles->vehicle . ".json";
$vehicles_list[$count_2]->queuing = false;
date_default_timezone_set('Asia/Manila');
$format = "%d-%m-%Y_%H:%M:%S";
$strf = strftime($format);
$route = $list_of_vehicles->route;
$directory = "./logs/" . $strf . "_" . $route . "_" .
$list_of_vehicles->vehicle . ".txt";
if(!copy("./vehicles/" . $puv_passengers, $directory)){
167
echo "error";
}
else{
try{
$puv_passenger_info =
json_decode(file_get_contents("./logs/" . $strf . "_" . $route . "_"
. $list_of_vehicles->vehicle . ".txt"));
array_push($puv_passenger_info, array("queuetime" =>
$queue_time, "leavetime" => $strf));
$altered_puv_passenger_info = fopen("./logs/" .
$strf . "_" . $route . "_" . $list_of_vehicles->vehicle . ".txt",
"w");
fwrite($altered_puv_passenger_info,
json_encode($puv_passenger_info));
fclose($altered_puv_passenger_info);
$passenger_count = 0;
$passenger_list_array =
json_decode(file_get_contents("./vehicles/" . $puv_passengers));
foreach($passenger_list_array as $passenger_name){
if($passenger_name->Name != ""){
$passenger_name->Name = "";
$passenger_name->Companion = "";
$passenger_name->Number = "";
$passenger_count += 1;
}
$count_3 += 1;
}
$passengers = $passenger_count . "/" . $count_3;
$save_log_directory = $connection->prepare("INSERT
INTO logs(Directory, Vehicle, Passengers, Route, LogTime, LogDate)
VALUES(:directory, :vehicle, :passengers, :route, now(), now())");
$save_log_directory->bindParam(':directory',
$directory);
$save_log_directory->bindParam(':vehicle', $data);
$save_log_directory->bindParam(':passengers',
$passengers);
$save_log_directory->bindParam(':route', $route);
$save_log_directory->execute();
$queuing_vehicles_file =
fopen('./vehicles/queuing_vehicles.json', 'w');
$all_vehicle_file =
fopen('./vehicles/vehicles.json', 'w');
$passenger_list_file = fopen("./vehicles/" .
$puv_passengers, 'w');
fwrite($queuing_vehicles_file,
json_encode($queuing_vehicles_list));
fwrite($all_vehicle_file,
json_encode($vehicles_list));
fwrite($passenger_list_file,
json_encode($passenger_list_array));
fclose($queuing_vehicles_file);
fclose($all_vehicle_file);
fclose($passenger_list_file);
echo "success";
break;
168
}catch(Exception $e){
echo "error";
echo $e;
}
}
}
$count_2 += 1;
}
break;
}
$count_1 += 1;
}
}
}
else{
echo "error";
}

12. Waiting passengers

Waiting passengers components (PHP and HTML):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
require './db_connection.php';
169
$passenger_count = $connection->prepare("SELECT COUNT(*) as count
FROM waiting_passengers WHERE Destination = :destination");
$destination_one = "valencia";
$passenger_count->bindParam(':destination', $destination_one);
try{
$passenger_count->execute();
$count_one = $passenger_count->fetchColumn();
}catch(Exception $e){
echo "Error";
}
echo "<div class='main-div'><div class='dest-div'>Valencia</div><div
class='waiting-div'>" . $count_one . "</div></div>";
$destination_two = "albuera";
$passenger_count->bindParam(':destination', $destination_two);
try{
$passenger_count->execute();
$count_two = $passenger_count->fetchColumn();
}catch(Exception $e){
echo "Error";
}
echo "<div class='main-div'><div class='dest-div'>Albuera</div><div
class='waiting-div'>" . $count_two . "</div></div>";
$destination_three = 'sabangbao';
$passenger_count->bindParam(':destination', $destination_three);
try{
$passenger_count->execute();
$count_three = $passenger_count->fetchColumn();
}catch(Exception $e){
echo "Error";
}
echo "<div class='main-div'><div
class='dest-div'>Sabang-Bao</div><div class='waiting-div'>" .
$count_three . "</div></div>";
$destination_four = 'puertobello';
$passenger_count->bindParam(':destination', $destination_four);
try{
$passenger_count->execute();
$count_four = $passenger_count->fetchColumn();
}catch(Exception $e){
echo "Error";
}
echo "<div class='main-div'><div
class='dest-div'>Puertobello</div><div class='waiting-div'>" .
$count_four . "</div></div>";

$connection = null;
?>

Server request and reply handle for waiting passengers (JavaScript):

function loadWaitingPassengers(){
const waitingPassengers = new XMLHttpRequest();
170
waitingPassengers.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-5-1').innerHTML =
this.responseText;
}
};
waitingPassengers.open("POST", "../admin_passenger_list.php",
true);
waitingPassengers.send();
}

Loop server request and reply handle for waiting passengers (JavaScript):

setInterval(function(){
loadWaitingPassengers();
}, 1500);

13. Returning PUVs

Returning PUVs component (PHP and HTML):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
171
$data = "";
if(isset($_POST['data'])){
$data = $_POST['data'];
}
$vehicles =
json_decode(file_get_contents('./vehicles/vehicles.json'));
echo "<table class='returning-vehicle-table'>";
echo "<tr class='rvt'>";
echo "<th>Vehicle</th>";
echo "<th>Operator</th>";
echo "<th>Driver</th>";
echo "<th>Route</th>";
echo "<th>Contact #</th>";
echo "<th>Returning</th>";
echo "</tr>";
if(sizeof($vehicles) > 0){
if($data != ''){
foreach($vehicles as $vehicle){
if($vehicle->route == $data || $vehicle->vehicle == $data){
echo "<tr>";
echo "<td>";
echo $vehicle->vehicle;
echo "</td>";
echo "<td>";
echo $vehicle->operator;
echo "</td>";
echo "<td>";
echo $vehicle->driver;
echo "</td>";
echo "<td>";
echo strtoupper($vehicle->route);
echo "</td>";
echo "<td>";
echo $vehicle->contact_num;
echo "</td>";
echo "<td>";
if($vehicle->returning){
$vh = '"' . $vehicle->vehicle . '"';
echo "<button style='box-shadow: -2px 2px 5px black;
background-color: #f1c40f; height: 20px; width: 20px; border-radius:
50px; border: none; margin-bottom: 5px;' onclick='vehicleStatus(" .
$vh . ")'></button>";
}else{
$vh = '"' . $vehicle->vehicle . '"';
echo "<button style='box-shadow: -2px 2px 5px black;
background-color: #2c3e50; height: 20px; width: 20px; border-radius:
50px; border: none; margin-bottom: 5px;' onclick='vehicleStatus(" .
$vh . ")'></button>";
}
echo "</td>";
echo "</tr>";
}
}
}else{
foreach($vehicles as $vehicle){
172
echo "<tr>";
echo "<td>";
echo $vehicle->vehicle;
echo "</td>";
echo "<td>";
echo $vehicle->operator;
echo "</td>";
echo "<td>";
echo $vehicle->driver;
echo "</td>";
echo "<td>";
echo strtoupper($vehicle->route);
echo "</td>";
echo "<td>";
echo $vehicle->contact_num;
echo "</td>";
echo "<td>";
if($vehicle->returning){
$vh = '"' . $vehicle->vehicle . '"';
echo "<button class='duty-buttton' style='box-shadow: -2px
2px 5px black; background-color: #f1c40f; height: 20px; width: 20px;
border-radius: 50px; border: none; margin-bottom: 5px;'
onclick='vehicleStatus(" . $vh . ")'></button>";
}else{
$vh = '"' . $vehicle->vehicle . '"';
echo "<button class='duty-buttton' style='box-shadow: -2px
2px 5px black; background-color: #2c3e50; height: 20px; width: 20px;
border-radius: 50px; border: none; margin-bottom: 5px;'
onclick='vehicleStatus(" . $vh . ")'></button>";
}
echo "</td>";
echo "</tr>";
}
}
}
else{
echo "<tr><td colspan='6'>No registered vehicles</td></tr>";
}

echo "</table>";
?>

Server request and reply handle for returning PUVs (JavaScript):

function loadReturningVehicles(){
if(document.getElementById('search-input').value != ''){
let searchedReturning = document.getElementById('search-
input').value;
const returningVehicles = new XMLHttpRequest();
returningVehicles.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-4-1-sub').innerHTML =
this.responseText;
173
}
};
returningVehicles.open("POST",
"../admin_returning_vehicle_list.php", true);
returningVehicles.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
returningVehicles.send("data=" + searchedReturning);
}else if(document.getElementById('searched-returning').value !=
''){
let searchedReturning = document.getElementById('searched-
returning').value;
const returningVehicles = new XMLHttpRequest();
returningVehicles.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-4-1-sub').innerHTML =
this.responseText;
}
};
returningVehicles.open("POST",
"../admin_returning_vehicle_list.php", true);
returningVehicles.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
returningVehicles.send("data=" + searchedReturning);
}else{
const returningVehicles = new XMLHttpRequest();
returningVehicles.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-4-1-sub').innerHTML =
this.responseText;
}
};
returningVehicles.open("POST",
"../admin_returning_vehicle_list.php", true);
returningVehicles.send();
}
}

Loop server request and reply handle for returning PUVs (JavaScript):

setInterval(function(){
loadReturningVehicles();
}, 1500);

When pressing the returning button (JavaScript):

function vehicleStatus(data){
const changeVehicleStatus = new XMLHttpRequest();
changeVehicleStatus.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == "success-on"){
returningSetSuccess('Vehicle set to return');

174
}
else if(this.responseText == "success-off"){
returningSetSuccess('Vehicle set to not return');
}
else{
returningSetError('Something went wrong');
}
}
}
changeVehicleStatus.open("POST",
"../admin_vehicle_returning_process.php", true);
changeVehicleStatus.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
changeVehicleStatus.send("data=" + data);
}

Returning process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
$vehicles =
json_decode(file_get_contents('./vehicles/vehicles.json'));
$data = $_POST['data'];

if(sizeof($vehicles) > 0){


foreach($vehicles as $vehicle){
if($vehicle->vehicle === $data){
if($vehicle->returning){
$vehicle->returning = false;
echo "success-off";
}
else{
$vehicle->returning = true;
echo "success-on";
}
break;
}
}
$file = fopen('./vehicles/vehicles.json', 'w');
fwrite($file, json_encode($vehicles));
fclose($file);
}
?>

175
14. Dispatcher Profile

Dispatcher profile components (HTML and PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
require './db_connection.php';

try{
$retrieve_dispatcher_list = $connection->prepare("SELECT * FROM
dispatchers ORDER BY FirstName");
$retrieve_dispatcher_list->execute();
$dispatchers = $retrieve_dispatcher_list->fetchAll();
if($retrieve_dispatcher_list->rowCount() > 0){
foreach($dispatchers as $dispatcher){
$fname = '"' . $dispatcher['FirstName'] . '"';
$mname = '"' . $dispatcher['MiddleName'] . '"';
$lname = '"' . $dispatcher['LastName'] . '"';
$suffix = '"' . $dispatcher['Suffix'] . '"';
$id = '"' . $dispatcher['ID'] . '"';
$contact = '"' . $dispatcher['Contact'] . '"';
$profile = '"' . $dispatcher['Profile'] . '"';
$pin = '"' . $dispatcher['PIN'] . '"';
176
$address = '"' . $dispatcher['Address'] . '"';
$name = '"' . $dispatcher['FirstName'] . " " .
$dispatcher['MiddleName'] . " " . $dispatcher['LastName'] . " " .
$dispatcher['Suffix'] . '"';
echo "<div class='container p-3 border' style='display: flex;
border-radius: 5px; margin-bottom: 5px;'>";
echo "<div class='dispatcher-prof-container'>";
echo "<div>";
if($dispatcher['Profile'] == ''){
echo "<img id='actual-pic'
src='../dispatcher_profile/adminUserProfile.png'>";
}else{
echo "<img id='actual-pic' src='." .
$dispatcher['Profile'] . "'>";
}
echo "</div>";
echo "</div>";
echo "<div style='margin-left: 5px; display: flex; flex-
direction: column; justify-content: center'>";
echo "<div class='p-2' style='color: #5DADE2'>";
echo "<b>" . $dispatcher['FirstName'] . " " .
$dispatcher['MiddleName'] . " " . $dispatcher['LastName'] . " " .
$dispatcher['Suffix'] . "</b>";
echo "</div>";
if($dispatcher['Address'] != "0"){
echo "<div style='margin-left: 8px; font-size: 13px'>";
echo $dispatcher['Address'] . ", Ormoc City";
echo "</div>";
}else{
echo "<div style='margin-left: 8px; font-size: 13px'>";
echo "Non-Resident";
echo "</div>";
}
echo "<div style='margin-left: 8px; font-size: 13px'>";
echo $dispatcher['Contact'];
echo "</div>";
echo "<div style='margin-left: 8px; font-size: 13px'>";
echo $dispatcher['PIN'] . " [PIN]";
echo "</div>";
echo "<div class='p-2'>";
echo "<span style='margin-right: 5px'><button type='button'
data-toggle='modal' data-target='#popupEdit' style='font-size:
10px;' class='btn btn-primary' onclick='editDispatcher(" . $id . ","
. $fname . "," . $mname . "," . $lname . "," . $suffix . "," .
$contact . "," . $profile . "," . $pin . "," . $address .
")'>Edit</button></span>";
echo "<button style='font-size: 10px;' type='button'
class='btn btn-danger' onclick='deleteDispatcher(" . $id . "," .
$name . ")'>Unregister</button>";
echo "</div>";
echo "</div>";
echo "</div>";
}
}else{

177
echo "<div class='container p-3 my-3 border' style='text-align:
center'>No registered dispatchers</div>";
}
$connection = null;
}catch(Exception $e){
echo "<div class='container p-3 my-3 border' style='text-align:
center'>Something went wrong</div>";
}

Dispatcher profile server request and reply handle (JavaScript):

function retrieveRegisteredDispatcher(){
Loader.open();
const retrieveDispatcher = new XMLHttpRequest();
retrieveDispatcher.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
Loader.close();
document.querySelector('.dispatchers-table-profile').innerHTML
= this.responseText;
}else{
Loader.open();
}
}
retrieveDispatcher.open("POST",
"../admin_dispatcher_editable_list.php", true);
retrieveDispatcher.send();
}

When pressing the edit button (JavaScript):

const editDispatcher = (id, fname, mname, lname, suffix, contact,


profile, pin, address) => {
const name = fname + " " + mname + " " + lname + " " + suffix;
document.getElementById('modalTitle').innerHTML = name;
document.getElementById('dis_f_name').value = fname;
document.getElementById('dis_m_name').value = mname;
document.getElementById('dis_l_name').value = lname;
document.getElementById('suffix').value = suffix;
document.getElementById('dis_c_num').value = contact.slice(1);
document.getElementById('address').value = address;
profileState = profile;
if(profile == ''){
document.getElementById('actual-pic').src =
"../dispatcher_profile/adminUserProfile.png";
}else{
document.getElementById('actual-pic').src = "." + profile;
}
document.getElementById('save-button').value = id;
document.getElementById('gen-pin').value = pin;
profilePic = profile;
pinState = pin;

178
}

Saving the edited dispatcher information (JavaScript):

const saveEditedData = (value) => {


let contactNumber = document.getElementById('dis_c_num');
let genPin = document.getElementById('gen-pin');
Loader.open();
if(contactNumber.checkValidity() && genPin.checkValidity()){
let changepin = false;
if(pinState != genPin.value){
changepin = 'true';
}
let dis_fname = document.getElementById('dis_f_name').value;
let dis_mname = document.getElementById('dis_m_name').value;
let dis_lname = document.getElementById('dis_l_name').value;
let invalid_str = /\d/;
if(invalid_str.test(dis_fname) || invalid_str.test(dis_mname) ||
invalid_str.test(dis_lname)){
Loader.close();
popupWarning('An invalid input was detected, please recheck
all the fields');
}else{
let invalid_char = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;
if(invalid_char.test(dis_fname) ||
invalid_char.test(dis_mname) || invalid_char.test(dis_lname)){
Loader.close();
popupWarning('An invalid input was detected, please recheck
all the fields');
}else{
let dis_cnum = document.getElementById('dis_c_num').value;
let dis_pin = document.getElementById('gen-pin').value;
let dis_suffix = document.getElementById('suffix').value;
let address = document.getElementById('address').value;
let name = dis_fname.trim() + dis_mname.trim() +
dis_lname.trim() + dis_suffix.trim();
const registerDispatch = new XMLHttpRequest();
registerDispatch.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == "success"){
uploadThePhoto(value, name);
}else if(this.responseText == "nochanges"){
if(choosenFile.value != ''){
uploadThePhoto(value, name);
}else{
Loader.close();
popupWarning('No changes are made');
}
}else if(this.responseText == "pinexist"){
Loader.close();
popupError('PIN already used, please generate another
one');
}else if(this.responseText == "error"){
179
Loader.close();
popupError('Something went wrong');
}else if(this.responseText == "incomplete"){
Loader.close();
popupWarning('Please fill all the fields');
}else if(this.responseText == "notallowed"){
popupInfo("Cannot edit a dispatcher that is on duty");
}else{
Loader.close();
popupError('Something went wrong');
}
console.log(this.responseText);
$('#popupEdit').modal('hide')
}else{
Loader.close();
$('#popupEdit').modal('hide')
popupError("Failed to save changes");
}
}
registerDispatch.open("POST",
"../admin_register_edited_dispatcher.php", true);
registerDispatch.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
registerDispatch.send("dis_fname=" + dis_fname.trim() +
"&dis_mname=" + dis_mname.trim() + "&dis_lname=" + dis_lname.trim()
+ "&dis_suffix=" + dis_suffix + "&dis_cnum=" + "0" + dis_cnum +
"&dis_pin=" + dis_pin + "&id=" + value + "&changepin=" + changepin +
"&address=" + address);
}
}
}else{
Loader.close();
popupWarning('An invalid input was detected, please recheck all
the fields');
}
}

Saving edited dispatcher information process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
if((isset($_POST['dis_fname']) && !empty(trim($_POST['dis_fname'])))
&& (isset($_POST['dis_mname']) && !empty(trim($_POST['dis_mname'])))

180
&& (isset($_POST['dis_lname']) && !
empty(trim($_POST['dis_lname']))) && (isset($_POST['dis_cnum']) && !
empty(trim($_POST['dis_cnum'])))
&& (isset($_POST['dis_pin']) && !empty(trim($_POST['dis_pin'])))
&& (isset($_POST['address']) && trim($_POST['address']) != "")){
try{
require './db_connection.php';
$pin = $_POST['dis_pin'];
$changepin = $_POST['changepin'];
$check_pin = $connection->prepare("SELECT * FROM dispatchers
WHERE PIN = :pin");
$check_pin->bindParam(":pin", $pin);
$check_pin->execute();
$count = $check_pin->fetchColumn();
if($count > 0 && $changepin == "true"){
echo "pinexist";
}else{
$id = $_POST['id'];
$check_duty = $connection->prepare("SELECT OnDuty FROM
dispatchers WHERE ID = :id");
$check_duty->bindParam(":id", $id);
$check_duty->execute();
$onduty = $check_duty->fetchAll();
if($onduty[0]["OnDuty"] == 0){
$fname = $_POST['dis_fname'];
$mname = $_POST['dis_mname'];
$lname = $_POST['dis_lname'];
$suffix = $_POST['dis_suffix'];
$contact = $_POST['dis_cnum'];
$address = $_POST['address'];
$update_dispatcher = $connection->prepare("UPDATE
dispatchers SET FirstName = :fname, MiddleName = :mname, LastName
= :lname, Suffix = :suffix, PIN = :pin, Contact = :contact, Address
= :address WHERE ID = :id");
$update_dispatcher->bindParam(':fname', $fname);
$update_dispatcher->bindParam(':mname', $mname);
$update_dispatcher->bindParam(':lname', $lname);
$update_dispatcher->bindParam(':suffix', $suffix);
$update_dispatcher->bindParam(':pin', $pin);
$update_dispatcher->bindParam(':contact', $contact);
$update_dispatcher->bindParam(':id', $id);
$update_dispatcher->bindParam(':address', $address);
$update_dispatcher->execute();
if($update_dispatcher->rowCount() > 0){
echo "success";
}else{
echo "nochanges";
}
}else{
echo "notallowed";
}
}
}catch(Exception $e){
echo "error";
}
181
}else{
echo "incomplete";
}
$connection = null;
?>

When pressing the unregister button (JavaScript):

function deleteDispatcher(data, name){


Swal.fire({
title: 'Are you sure you want to remove ' + name + '?',
showCancelButton: true,
confirmButtonText: 'Unregister',
}).then((result) => {
if (result.isConfirmed) {
Loader.open();
const delDispatcher = new XMLHttpRequest();
delDispatcher.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
Loader.close();
if(this.responseText == "success"){
retrieveRegisteredDispatcher();
Swal.fire('Dispatcher successfully removed', '',
'success');
}else if(this.responseText == "error"){
popupError('Something went wrong');
}else if(this.responseText == "notallowed"){
popupInfo('Dispatcher is on duty, deletion is
restricted');
}else{
popupError('Something went wrong');
}
console.log(this.responseText);
}else{
Loader.close();
popupError('Failed to remove dispatcher');
}
}
delDispatcher.open("POST", "../admin_delete_dispatcher.php",
true);
delDispatcher.setRequestHeader("Content-type", "application/x-
www-form-urlencoded");
delDispatcher.send("data=" + data);
} else if (result.isDenied) {
Swal.fire('Nothing has been done.', '', 'info')
}
})
}

Unregister dispatcher process (PHP):

182
<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
require 'db_connection.php';
$id = $_POST['data'];
try{
$select_file_directory = $connection->prepare("SELECT Profile,
OnDuty FROM dispatchers WHERE ID = :id");
$select_file_directory->bindParam(":id", $id);
$select_file_directory->execute();
$data = $select_file_directory->fetchAll();
if($data[0]['OnDuty'] == 0){
if($data[0]['Profile'] != ''){
if(file_exists($data[0]['Profile'])){
if(unlink($data[0]['Profile'])){
$delete_dispatcher = $connection->prepare("DELETE FROM
dispatchers WHERE ID = :id");
$delete_dispatcher->bindParam(':id', $id);
$delete_dispatcher->execute();
echo "success";
}else{
echo "error";
}
}else{
echo "error";
}
}else{
$delete_dispatcher = $connection->prepare("DELETE FROM
dispatchers WHERE ID = :id");
$delete_dispatcher->bindParam(':id', $id);
$delete_dispatcher->execute();
echo "success";
}
$connection = null;
}else{
echo "notallowed";
}
}catch(Exception $e){
echo "error";
}
?>

183
15. Vehicle profile

Vehicle profile components (HTML and PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
$data = "";
if(isset($_POST['data'])){
$data = $_POST['data'];
}
try{
require './db_connection.php';
$retrieve_registered_puv = $connection->prepare("SELECT * FROM
registered_vehicles WHERE Status = 'Active'");
$retrieve_registered_puv->execute();
$puvs = $retrieve_registered_puv->fetchAll();
if($retrieve_registered_puv->rowCount() > 0){
foreach($puvs as $puv){
$fname = '"' . $puv['FirstName'] . '"';
$mname = '"' . $puv['MiddleName'] . '"';
$lname = '"' . $puv['LastName'] . '"';
$suffix = '"' . $puv['Suffix'] . '"';
$capacity = '"' . $puv['Capacity'] . '"';
$route = '"' . $puv['Route'] . '"';
$plateno = '"' . $puv['PlateNo'] . '"';

184
$tel = '"' . $puv['Contact'] . '"';
$dfname = '"' . $puv['DFirstName'] . '"';
$dmname = '"' . $puv['DMiddleName'] . '"';
$dlname = '"' . $puv['DLastName'] . '"';
$dsuffix = '"' . $puv['DSuffix'] . '"';
$dcontact = '"' . $puv['DContact'] . '"';
$daddress = '"' . $puv['DAddress'] . '"';
$address = '"' . $puv['Address'] . '"';
$pic = '"' . $puv['VehicleProfile'] . '"';
echo "<div class='container p-3 border' style='border-radius:
5px; margin-bottom: 5px; display: flex; position: relative;'>";
if($puv['VehicleProfile'] != ""){
echo "<div style='padding: 5px; display: inline-block;'><img
style='width: 200px; height: 200px;' src='." .
$puv['VehicleProfile'] . "'></div>";
}else{
echo "<div style='padding: 5px; border-radius: 5px; display:
inline-block;'><img style='width: 200px; height:
200px;'src='../vehicle_images/vehicleImage.png'></div>";
}
echo "<div style='display: flex; flex-direction: column;
align-items: flex-start; justify-content: space-around; padding-
left: 10px;'>";
echo "<div style='display: flex; align-items: center;'><div
style='font-size: 2em; font-weight: bold;'>" . $puv['PlateNo'] .
"</div>";
echo "<div style='margin-left: 5px; font-size: 18px;
background-color: #29b563; color: black; padding: 5px; border-
radius: 3px;'>" . strtoupper($puv['Route']) . "</div></div>";
echo "<div style='font-size: 13px;'>";
echo "<span style='font-weight: bold;'>Capacity:&ensp;</span>"
. $puv['Capacity'] . "<br>";
echo "<span style='font-weight: bold;'>Operator:&ensp;</span>"
. $puv['FirstName'] . " " . $puv['MiddleName'] . " " .
$puv['LastName'] . " " . $puv['Suffix'] . "<br>";
if($puv['Address'] != "0"){
echo "<span style='font-weight: bold;'>Operator's
address:&ensp;</span>" . $puv['Address'] . ", Ormoc City<br>";
}else{
echo "<span style='font-weight: bold;'>Operator's
address:&ensp;</span>Non-Resident<br>";
}
echo "<span style='font-weight: bold;'>Operator's mobile
#:&ensp;</span>" . $puv['Contact'] . "<br>";
echo "<span style='font-weight: bold;'>Driver:&ensp;</span>" .
$puv['DFirstName'] . " " . $puv['DMiddleName'] . " " .
$puv['DLastName'] . " " . $puv['DSuffix'] . "<br>";
if($puv['DAddress'] != "0"){
echo "<span style='font-weight: bold;'>Driver's
address:&ensp;</span>" . $puv['DAddress'] . ", Ormoc City<br>";
}else{
echo "<span style='font-weight: bold;'>Driver's
address:&ensp;</span>Non-Resident<br>";
}

185
echo "<span style='font-weight: bold;'>Driver's mobile
#:&ensp;</span>" . $puv['DContact'] . "<br>";
echo "</div>";
echo "</div>";
echo "<div style='position: absolute; right: 10px; bottom:
10px;'>";
echo "<span style='margin-right: 5px'><button type='button'
data-toggle='modal' data-target='#popupEdit' style='font-size:
10px;' class='btn btn-primary' onclick='editData(" . $fname . "," .
$mname . "," . $lname . "," . $suffix . "," . $capacity .
"," . $route . "," . $plateno . "," . $tel . "," . $dfname .
"," . $dmname . "," . $dlname . "," . $dsuffix . "," . $dcontact .
"," . $daddress . "," . $address . "," . $pic
.")'>Edit</button></span>";
echo "<button style='font-size: 10px;' type='button'
class='btn btn-danger' onclick='deletePUV(" . $plateno .
")'>Remove</button>";
echo "</div>";
echo "<div style='position: absolute; right: 0; top: 0;
border-radius: 5px;' title='Click to download'>";
echo "<a download href='../qrs/" . $puv['PlateNo'] . ".png'>";
echo "<img style='width: 150px; height: 150px;'
src='../qrs/" . $puv['PlateNo'] . ".png" . "'></img></a></div>";
echo "</div>";
}
}else{
echo "<div class='container p-3 my-3 border' style='border-
radius: 5px; text-align: center'>No registered PUV.</div>";
}
}catch(Exception $e){
echo "<div class='container p-3 my-3 border' style='border-radius:
5px; text-align: center'>Something went wrong.</div>";
}
?>

When pressing edit button (JavaScript):

function editData(fname, mname, lname, suffix, capacity, route,


plateno, contact, dfname, dmname, dlname, dsuffix, dcontact,
daddress, address, image){
document.getElementById('modalTitle').innerHTML = plateno;
document.getElementById('rt').value = route;
document.getElementById('cpcty').value = capacity;
document.getElementById('f_name').value = fname;
document.getElementById('m_name').value = mname;
document.getElementById('l_name').value = lname;
document.getElementById('suffix').value = suffix;
document.getElementById('c_num').value = contact.slice(1);
document.getElementById('save-button').value = plateno;
document.getElementById('df_name').value = dfname;
document.getElementById('dm_name').value = dmname;
document.getElementById('dl_name').value = dlname;
document.getElementById('dsuffix').value = dsuffix;
186
document.getElementById('dc_num').value = dcontact.slice(1);
document.getElementById('daddress').value = daddress;
document.getElementById('address').value = address;
if(image == ''){
document.getElementById('actual-pic').src =
"../vehicle_images/vehicleImage.png";
}else{
document.getElementById('actual-pic').src = "." + image;
}
}

Saving the edited PUV information (JavaScript):

const saveEditedData = (value) => {


let contactNumber = document.getElementById('c_num');
let dcontactNumber = document.getElementById('dc_num');
Loader.open();
if(contactNumber.checkValidity() &&
dcontactNumber.checkValidity()){
let f_name = document.getElementById('f_name').value;
let m_name = document.getElementById('m_name').value;
let l_name = document.getElementById('l_name').value;
let df_name = document.getElementById('df_name').value;
let dm_name = document.getElementById('dm_name').value;
let dl_name = document.getElementById('dl_name').value;
let invalid_str = /\d/;
if(invalid_str.test(f_name) || invalid_str.test(m_name) ||
invalid_str.test(l_name) || invalid_str.test(df_name) ||
invalid_str.test(dm_name) || invalid_str.test(dl_name)){
Loader.close();
popupWarning('Numbers are not allowed in names');
}else{
let invalid_char = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;
if(invalid_char.test(f_name) || invalid_char.test(m_name) ||
invalid_char.test(l_name) || invalid_char.test(df_name) ||
invalid_char.test(dm_name) || invalid_char.test(dl_name)){
Loader.close();
popupWarning('Special characters are not allowed in names');
}else{
let dsuffix = document.getElementById('dsuffix').value;
let suffix = document.getElementById('suffix').value;
let c_num = document.getElementById('c_num').value;
let dc_num = document.getElementById('dc_num').value;
let address = document.getElementById('address').value;
let daddress = document.getElementById('daddress').value;
let rt = document.getElementById('rt').value;
let cpcty = document.getElementById('cpcty').value;
if(cpcty > 50 || cpcty < 0){
Loader.close();
popupWarning('Capacity exceeds the limitations');
}else{
parameter = value + '_' + rt;
const registerPUV = new XMLHttpRequest();
187
registerPUV.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if(this.responseText == "notallowed"){
Loader.close();
popupInfo('Cannot edit a vehicle that is on queue');
}else if(this.responseText == 'nochanges'){
if(choosenFile.value != ''){
uploadThePhoto(value);
}else{
Loader.close();
popupWarning('No changes are made');
}
}else if(this.responseText == "incomplete"){
popupWarning('Please fill all the fields');
}
else if(this.responseText == "error"){
popupError('Something went wrong');
}
else if(this.responseText == "success"){
uploadThePhoto(value);
}
else{
popupError('Something went wrong');
}
console.log(this.responseText);
$('#popupEdit').modal('hide');
}
};
registerPUV.open("POST",
"../admin_register_edited_puv.php", true);
registerPUV.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
registerPUV.send("fname=" + f_name.trim() + "&mname=" +
m_name.trim() + "&lname=" + l_name.trim() + "&suffix=" + suffix
+ "&cnum=0" + c_num + "&plateno=" + value + "&route=" + rt
+ "&capacity=" + cpcty + "&dfname=" + df_name.trim() + "&dmname="
+ dm_name.trim() + "&dlname=" + dl_name.trim() +
"&dsuffix=" + dsuffix + "&dcnum=0" + dc_num + "&daddress=" +
daddress + "&address=" + address);
}
}
}
}else{
Loader.close();
popupWarning('Invalid input');
}
}

Saving edited PUV information process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
188
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}
try{
$queuing_vehicles =
json_decode(file_get_contents("./vehicles/queuing_vehicles.json"));
$plateno = $_POST['plateno'];
$proceed = true;
foreach($queuing_vehicles as $vehicle){
if($vehicle->vehicle == $plateno){
$proceed = false;
break;
}
}
if($proceed){
if((isset($_POST['fname']) && !empty(trim($_POST['fname']))) &&
(isset($_POST['mname']) && !empty(trim($_POST['mname'])))
&& (isset($_POST['lname']) && !empty(trim($_POST['lname'])))
&& (isset($_POST['cnum']) && !empty(trim($_POST['cnum'])))
&& (isset($_POST['route']) && !empty(trim($_POST['route'])))
&& (isset($_POST['capacity']) && !empty(trim($_POST['capacity'])))
&& (isset($_POST['dfname']) && !empty(trim($_POST['dfname'])))
&& (isset($_POST['dmname']) && !empty(trim($_POST['dmname'])))
&& (isset($_POST['dlname']) && !empty(trim($_POST['dlname'])))
&& (isset($_POST['dcnum']) && !empty(trim($_POST['dcnum'])))
&& (isset($_POST['address']) && trim($_POST['address']) != "")
&& (isset($_POST['daddress']) && trim($_POST['daddress']) !=
"")){
require "./db_connection.php";
$route = $_POST['route'];
$capacity = $_POST['capacity'];
$firstname = $_POST['fname'];
$middlename = $_POST['mname'];
$lastname = $_POST['lname'];
$suffix = $_POST['suffix'];
$contact = $_POST['cnum'];
$dfname = $_POST['dfname'];
$dmname = $_POST['dmname'];
$dlname = $_POST['dlname'];
$dsuffix = $_POST['dsuffix'];
$dcnum = $_POST['dcnum'];
$daddress = $_POST['daddress'];
$address = $_POST['address'];
$plateno = $_POST['plateno'];
$update_puv_info = $connection->prepare("UPDATE
registered_vehicles SET Route = :route, Capacity = :capacity,
FirstName = :firstname,
MiddleName
= :middlename, LastName = :lastname, Suffix = :suffix, Contact
= :contact,

189
Address = :address,
DFirstName = :dfname, DMiddleName = :dmname, DLastName = :dlname,
DSuffix = :dsuffix,
DContact = :dcontact, DAddress = :daddress WHERE PlateNo
= :plateno");
$update_puv_info->bindParam(":route", $route);
$update_puv_info->bindParam(":capacity", $capacity);
$update_puv_info->bindParam(":firstname", $firstname);
$update_puv_info->bindParam(":middlename", $middlename);
$update_puv_info->bindParam(":lastname", $lastname);
$update_puv_info->bindParam(":suffix", $suffix);
$update_puv_info->bindParam(":contact", $contact);
$update_puv_info->bindParam(":address", $address);
$update_puv_info->bindParam(":dfname", $dfname);
$update_puv_info->bindParam(":dmname", $dmname);
$update_puv_info->bindParam(":dlname", $dlname);
$update_puv_info->bindParam(":dsuffix", $dsuffix);
$update_puv_info->bindParam(":dcontact", $dcnum);
$update_puv_info->bindParam(":daddress", $daddress);
$update_puv_info->bindParam(":plateno", $plateno);
$update_puv_info->execute();
if($update_puv_info->rowCount() > 0){
$puv =
json_decode(file_get_contents("./vehicles/vehicles.json"));
foreach($puv as $vehicle){
if($vehicle->vehicle == $plateno){
$vehicle->operator = $firstname . " " . $middlename .
" " . $lastname . " " . $suffix;
$vehicle->driver = $dfname . " " . $dmname . " " .
$dlname . " " . $dsuffix;
$vehicle->contact_num = $contact;
$vehicle->route = $route;
$vehicle->capacity = $capacity;
break;
}
}
$file = fopen("./vehicles/vehicles.json", "w");
fwrite($file, json_encode($puv));
fclose($file);
echo "success";
}else{
echo "nochanges";
}
}else{
echo "incomplete";
}
}else{
echo "notallowed";
}
}catch(Exception $e){
echo $e;
}
?>

190
When pressing the remove button (JavaScript):

function deletePUV(plateno){
Swal.fire({
title: 'Are you sure you want to remove ' + plateno + '?',
showCancelButton: true,
confirmButtonText: 'Unregister',
}).then((result) => {
if (result.isConfirmed) {
Loader.open();
const delPUV = new XMLHttpRequest();
delPUV.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
Loader.close();
if(this.responseText == "success"){
retrieveRegisteredPUV();
Swal.fire('PUV successfully removed', '', 'success');
}else if(this.responseText == "notallowed"){
popupInfo('Cannot remove a vehicle that is on queue');
}else if(this.responseText == "error"){
popupError('Something went wrong');
}else{
popupError('Something went wrong');
}
console.log(this.responseText);
}else{
Loader.close();
popupError('Failed to remove dispatcher');
}
}
delPUV.open("POST", "../admin_delete_puv.php", true);
delPUV.setRequestHeader("Content-type", "application/x-www-
form-urlencoded");
delPUV.send("data=" + plateno);
}else if(result.isDenied) {
Swal.fire('Nothing has been done.', '', 'info')
}
})
}

Removing PUV process (PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
header('Location: ./');
}

191
$data = "";
if(isset($_POST['data'])){
$data = $_POST['data'];
}
try{
$plateno = $_POST['data'];
$queuing_vehicles =
json_decode(file_get_contents("./vehicles/queuing_vehicles.json"));
$proceed = true;
foreach($queuing_vehicles as $queued_vehicle){
if($queued_vehicle->vehicle == $plateno){
$proceed = false;
break;
}
}

if($proceed){
require './db_connection.php';
$data = $_POST['data'];
$vehicle_is_queuing = false;
$count_one = 0;
$count_two = 0;
require './db_connection.php';
$vehicles =
json_decode(file_get_contents('./vehicles/vehicles.json'));
foreach($vehicles as $vehicle){
if($vehicle->vehicle == $data){
$vehicle_name = $vehicle->vehicle;
$route = $vehicle->route;
array_splice($vehicles, $count_one, 1);
$queuing_vehicles =
json_decode(file_get_contents('./vehicles/queuing_vehicles.json'));
foreach($queuing_vehicles as $queuing_puvs){
if($queuing_puvs->vehicle == $data){
$vehicle_is_queuing = true;
array_splice($queuing_vehicles, $count_two, 1);
$delete_vehicle = $connection->prepare("UPDATE
registered_vehicles SET Status = 'Deleted', VehicleProfile = ''
WHERE PlateNo = :platenumber");
$delete_vehicle->bindParam(":platenumber", $data);
try{
if(!unlink("./vehicles/" . $route . "_" .
$vehicle_name . ".json")){
echo "error";
}else{
if(!unlink("./qrs/" . $vehicle_name . ".png")){
echo "error";
}
else{
$delete_vehicle->execute();
$vehicles_file = fopen('./vehicles/vehicles.json',
'w');
$vehicles_to_save = json_encode($vehicles);
fwrite($vehicles_file, $vehicles_to_save);
fclose($vehicles_file);
192
$queuing_vehicles_file =
fopen('./vehicles/queuing_vehicles.json', 'w');
$queuing_vehicles_to_save =
json_encode($queuing_vehicles);
fwrite($queuing_vehicles_file,
$queuing_vehicles_to_save);
fclose($queuing_vehicles_file);
echo "success";
}
}
}catch(Exception $e){
echo "error";
}
break;
}
$count_two += 1;
}
if(!$vehicle_is_queuing){
$delete_vehicle = $connection->prepare("UPDATE
registered_vehicles SET Status = 'Deleted', VehicleProfile = ''
WHERE PlateNo = :platenumber");
$delete_vehicle->bindParam(":platenumber", $data);
try{
if(!unlink("./vehicles/" . $route . "_" .
$vehicle_name . ".json")){
echo "error";
}else{
if(!unlink("./qrs/" . $vehicle_name . ".png")){
echo "error";
}
else{
$select_profile = $connection->prepare("SELECT
VehicleProfile FROM registered_vehicles WHERE PlateNo
= :platenumber");
$select_profile->bindParam(":platenumber", $data);
$select_profile->execute();
$profile_dir = $select_profile->fetchColumn();
if($profile_dir != ""){
if(!unlink($profile_dir)){
echo "error";
}else{
$delete_vehicle->execute();
$vehicles_file =
fopen('./vehicles/vehicles.json', 'w');
$vehicles_to_save = json_encode($vehicles);
fwrite($vehicles_file, $vehicles_to_save);
fclose($vehicles_file);
echo "success";
}
}else{
$delete_vehicle->execute();
$vehicles_file = fopen('./vehicles/vehicles.json',
'w');
$vehicles_to_save = json_encode($vehicles);
fwrite($vehicles_file, $vehicles_to_save);
193
fclose($vehicles_file);
echo "success";
}
}
}
}catch(Exception $e){
echo "error";
}
}
break;
}
$count_one += 1;
}
}else{
echo "notallowed";
}
}catch(Exception $e){
echo "error";
}
?>

16. Vehicle and passenger logs

Vehicle and passenger logs components (HTML and PHP):

<?php
session_start();
if(isset($_SESSION['loggedin'])){
if(!$_SESSION['loggedin']){
header('Location: ./');
}
}
else{
194
header('Location: ./');
}
$data = "";
require './db_connection.php';
if(isset($_POST['data'])){
if($_POST['data'] == 'latest'){
$retrieve_logs = $connection->prepare("SELECT logs.LogId,
logs.Directory, logs.Vehicle, logs.Passengers, logs.Route,
logs.LogDate, logs.LogTime,

registered_vehicles.FirstName, registered_vehicles.MiddleName,
registered_vehicles.LastName, registered_vehicles.Suffix,
registered_vehicles.Contact,

registered_vehicles.Address, registered_vehicles.DFirstName,
registered_vehicles.DMiddleName, registered_vehicles.DLastName,
registered_vehicles.DSuffix,

registered_vehicles.DContact, registered_vehicles.DAddress FROM logs


INNER JOIN registered_vehicles ON logs.Vehicle =
registered_vehicles.PlateNo ORDER BY LogId DESC");
}elseif($_POST['data'] == 'oldest'){
$retrieve_logs = $connection->prepare("SELECT logs.LogId,
logs.Directory, logs.Vehicle, logs.Passengers, logs.Route,
logs.LogDate, logs.LogTime,

registered_vehicles.FirstName, registered_vehicles.MiddleName,
registered_vehicles.LastName, registered_vehicles.Suffix,
registered_vehicles.Contact,

registered_vehicles.Address, registered_vehicles.DFirstName,
registered_vehicles.DMiddleName, registered_vehicles.DLastName,
registered_vehicles.DSuffix,

registered_vehicles.DContact, registered_vehicles.DAddress FROM logs


INNER JOIN registered_vehicles ON logs.Vehicle =
registered_vehicles.PlateNo ORDER BY LogId ASC");
}elseif($_POST['data'] == 'alphabetically'){
$retrieve_logs = $connection->prepare("SELECT logs.LogId,
logs.Directory, logs.Vehicle, logs.Passengers, logs.Route,
logs.LogDate, logs.LogTime,

registered_vehicles.FirstName, registered_vehicles.MiddleName,
registered_vehicles.LastName, registered_vehicles.Suffix,
registered_vehicles.Contact,

registered_vehicles.Address, registered_vehicles.DFirstName,
registered_vehicles.DMiddleName, registered_vehicles.DLastName,
registered_vehicles.DSuffix,

registered_vehicles.DContact, registered_vehicles.DAddress FROM logs


INNER JOIN registered_vehicles ON logs.Vehicle =
registered_vehicles.PlateNo ORDER BY logs.Vehicle ASC");
}
195
}elseif(isset($_POST['startdate']) && isset($_POST['enddate'])){
$start_date = $_POST['startdate'];
$end_date = $_POST['enddate'];
$retrieve_logs = $connection->prepare("SELECT logs.LogId,
logs.Directory, logs.Vehicle, logs.Passengers, logs.Route,
logs.LogDate, logs.LogTime,

registered_vehicles.FirstName, registered_vehicles.MiddleName,
registered_vehicles.LastName, registered_vehicles.Suffix,
registered_vehicles.Contact,

registered_vehicles.Address, registered_vehicles.DFirstName,
registered_vehicles.DMiddleName, registered_vehicles.DLastName,
registered_vehicles.DSuffix,

registered_vehicles.DContact, registered_vehicles.DAddress FROM logs


INNER JOIN registered_vehicles ON logs.Vehicle =
registered_vehicles.PlateNo WHERE logs.LogDate BETWEEN :startdate
AND :endate");
$retrieve_logs->bindParam(":startdate", $start_date);
$retrieve_logs->bindParam(":endate", $end_date);
}else{
$retrieve_logs = $connection->prepare("SELECT logs.LogId,
logs.Directory, logs.Vehicle, logs.Passengers, logs.Route,
logs.LogDate, logs.LogTime,

registered_vehicles.FirstName, registered_vehicles.MiddleName,
registered_vehicles.LastName, registered_vehicles.Suffix,
registered_vehicles.Contact,

registered_vehicles.Address, registered_vehicles.DFirstName,
registered_vehicles.DMiddleName, registered_vehicles.DLastName,
registered_vehicles.DSuffix,

registered_vehicles.DContact, registered_vehicles.DAddress FROM logs


INNER JOIN registered_vehicles ON logs.Vehicle =
registered_vehicles.PlateNo");
}
try{
$retrieve_logs->execute();
$logs = $retrieve_logs->fetchAll();
if(sizeof($logs) > 0){
foreach($logs as $log){
echo "<div id='vehicle-logs-container' style='margin-bottom:
3px;'>";
echo "<div>";
echo "<div class='card-header' id='" . $log['LogId'] . "'>";
echo "<h5 class='mb-0'>";
echo "<button style='width: 100%;' class='btn btn-link
collapsed' data-toggle='collapse' data-target='#" .
$log['Vehicle'] . "_" . $log['LogId'] . "' aria-expanded='true'
aria-controls='collapseOne'>";
echo "<div style='display: flex; align-items: center; justify-
content: space-between; width: 100%;'>";
196
echo "<div style='display: flex; align-items: center;'>";
echo "<div style='padding-right: 5px'><i class='fas fa-
chevron-right'></i></div>";
echo "<i class='fas fa-file' style='font-size: 35px;'></i>";
echo "<div style='width: 100px; padding: 5px;' id='" .
$log['Route'] . "_" . $log['LogId'] . "'>" . $log['Vehicle'] .
"</div>";
echo "</div>";
echo "<div>Created at: <span id=" . $log['LogId'] . "_" .
$log['LogId'] . ">" . $log['LogDate'] . "_" . $log['LogTime'] .
"</span></div>";
echo "</div>";
echo "</button>";
echo "</h5>";
echo "</div>";
echo "<div id='" . $log['Vehicle'] . "_" . $log['LogId'] . "'
style='text-align: center;' class='collapse' aria-labelledby='" .
$log['LogId'] . "' data-parent='#vehicle-logs-container'>";
$vehicle_name = '"' . $log['Route'] . "_" . $log['LogId'] .
'"';
$vh_timestamp = '"' . $log['LogId'] . "_" . $log['LogId'] .
'"';
$area_to_print = '"' . basename($log['Directory']) . '"';
echo "<div display='flex' style='margin: 10px 0 10px
0'><button class='btn btn-primary' onclick='saveLogPDF(" .
$vehicle_name . "," . $vh_timestamp . "," . $area_to_print .
")'>SAVE AS PDF</button></div>";
echo "<div id='" . basename($log['Directory']) . "'
class='card-body'>";
echo "<div style='text-align: center'>";
echo "<img style='width: 100px; height: 100px;'
src='./images/logoQrmoc.png'>";
echo "<div style='font-size: 14px; font-family: Times New
Roman; padding: 5px 0 3px 0; font-weight: bold'>";
echo "Authentic Log of " . $log['Vehicle'] . " Operated by " .
$log['FirstName'] . " " . $log['MiddleName'] . " " .
$log['LastName'] . " " . $log['Suffix'] . " going to "
. strtoupper($log['Route']) . " droven by " .
$log['DFirstName'] . " " . $log['DMiddleName'] . " " .
$log['DLastName'] . " " . $log['DSuffix'] ."</div>";
echo "<div style='font-size: 14px; font-family: Times New
Roman; padding: 2px 0 20px 0; font-weight: bold'>Generated by Q R M
O C - Queuing Passenger Assistance System</div>";
echo "</div>";
$log_content =
json_decode(file_get_contents($log['Directory']));
echo "<table style='width: 100%'>";
echo
"<tr><th>No</th><th>Passenger</th><th>Companion</th><th>Mobile
#</th></tr>";
$count = 0;
foreach($log_content as $info){
if(isset($info->queuetime) && isset($info->leavetime)){
echo "<table style='width: 100%'>";

197
echo "<tr><th>Time Queued</th><th>Time
Departed</th></tr>";
echo "<tr><td>" . $info->queuetime . "</td><td>" . $info-
>leavetime . "</td></tr>";
echo "</table>";
}else{
$count += 1;
echo "<tr>";
echo "<td>" . $count . "</td>";
echo "<td>";
if($info->Name == ""){
echo "N/A";
}else{
echo $info->Name;
}
echo "</td>";
echo "<td>";
if($info->Companion == 'true'){
echo "<i class='fas fa-check'></i>";
}else{
echo "<i class='fas fa-times'></i>";
}
echo "</td>";
echo "<td>";
if($info->Number == ""){
echo "N/A";
}else{
echo $info->Number;
}
echo "</td>";
echo "</tr>";
}
}
echo "</table>";
echo "<div style='padding: 5px 0 0 0; display: flex; justify-
content: space-between;'>";
echo "<div style='font-family: Times New Roman; font-size:
14px'>Number of Passengers: " . $log['Passengers'] . "</div>";
echo "<div style='font-family: Times New Roman; font-size:
14px'>Made possible by J<sup>3</sup></div>";
echo "</div>";
echo "</div>";
echo "</div>";
echo "</div>";
echo "</div>";
}
}else{
echo "<div class='container border' style='text-align: center;
padding: 10px;'>No logs found</div>";
}
}catch(Exception $e){
echo "<div class='container border' style='text-align: center;
padding: 10px;'>Something went wrong</div>";
}
echo "</table>";
198
?>

Server request and reply handle for vehicle and passenger logs (PHP and HTML):

function retrieveLogs(){
let search = document.getElementById('search-input').value;
let data = document.getElementById('sort-option').value;
if(search != ''){
const logs = new XMLHttpRequest();
logs.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-7-1-sub').innerHTML =
this.responseText;
}
}
logs.open('POST', '../admin_search_logs.php', true);
logs.setRequestHeader("Content-type", "application/x-www-form-
urlencoded");
logs.send("data=" + search);
}else if(data == 'latest'){
document.getElementById('moreoptions').style.display = 'none';
const logs = new XMLHttpRequest();
logs.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-7-1-sub').innerHTML =
this.responseText;
}
}
logs.open('POST', '../admin_retrieve_logs.php', true);
logs.setRequestHeader("Content-type", "application/x-www-form-
urlencoded");
logs.send("data=" + data);
}else if(data == 'oldest'){
document.getElementById('moreoptions').style.display = 'none';
const logs = new XMLHttpRequest();
logs.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-7-1-sub').innerHTML =
this.responseText;
}
}
logs.open('POST', '../admin_retrieve_logs.php', true);
logs.setRequestHeader("Content-type", "application/x-www-form-
urlencoded");
logs.send("data=" + data);
}else if(data == 'alphabetically'){
document.getElementById('moreoptions').style.display = 'none';
const logs = new XMLHttpRequest();
logs.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-7-1-sub').innerHTML =
this.responseText;
}
199
}
logs.open('POST', '../admin_retrieve_logs.php', true);
logs.setRequestHeader("Content-type", "application/x-www-form-
urlencoded");
logs.send("data=" + data);
}else if(data == 'moreoptions'){
document.getElementById('moreoptions').style.display = 'block';
let startDate = document.getElementById('start-date').value;
let endDate = document.getElementById('end-date').value;
if(startDate != '' && endDate != ''){
const logs = new XMLHttpRequest();
logs.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-7-1-sub').innerHTML =
this.responseText;
}
}
logs.open('POST', '../admin_retrieve_logs.php', true);
logs.setRequestHeader("Content-type", "application/x-www-form-
urlencoded");
logs.send("startdate=" + startDate + "&enddate=" + endDate);
}
}else{
const logs = new XMLHttpRequest();
logs.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
document.querySelector('.subfield-7-1-sub').innerHTML =
this.responseText;
}
}
logs.open('POST', '../admin_retrieve_logs.php', true);
logs.send();
}
}

Saving the logs as PDF (JavaScript):

function saveLogPDF(vhname, vhlogdate, doc){


let areaToPrint = document.getElementById(doc);
html2pdf(areaToPrint, {
filename: document.getElementById(vhname).innerHTML + "_" +
document.getElementById(vhlogdate).innerHTML + '.pdf'
});
}

200
Dispatcher’s Mobile Application

1. Log in

Logging in logic (React Native Framework):

const Pone = ({color}) => (


<View style={{width: 15,
height: 15,
borderWidth: 1,
borderRadius: 50,
borderColor: '#566573',
backgroundColor: color
}}
>
</View>
)
201
const Ptwo = ({color}) => (
<View style={{width: 15,
height: 15,
borderWidth: 1,
borderRadius: 50,
borderColor: '#566573',
backgroundColor: color
}}
>
</View>
)

const Pthree = ({color}) => (


<View style={{width: 15,
height: 15,
borderWidth: 1,
borderRadius: 50,
borderColor: '#566573',
backgroundColor: color
}}
>
</View>
)

const Pfour = ({color}) => (


<View style={{width: 15,
height: 15,
borderWidth: 1,
borderRadius: 50,
borderColor: '#566573',
backgroundColor: color
}}
>
</View>
)

const [pinOne, setPinOne] = useState(false);


const [pinTwo, setPinTwo] = useState(false);
const [pinThree, setPinThree] = useState(false);
const [pinFour, setPinFour] = useState(false);
const [pinCount, setPinCount] = useState(1);
const [pin, setPin] = useState('');
const [signProcess, setSignProcess] = useState('');
const [signInStatus, setSignInStatus] = useState('');
const [iconType, setIconType] = useState('');
const [serverStatus, setServerStatus] = useState(false);

const reset = () => {


setPin('');
setPinCount(1);
setPinOne(false);
setPinTwo(false);
setPinThree(false);
setPinFour(false);
202
}

const buttonPress = (value) => {


setPinCount(pinCount + 1);
setPin(pin + value.toString());
if(pinCount == 1){
setPinOne(true);
setIconType('');
setSignInStatus('');
}else if(pinCount == 2){
setPinTwo(true);
}else if(pinCount == 3){
setPinThree(true);
}else if(pinCount == 4){
setPinFour(true);
setIconType(<Ionicons name='hand-right-sharp' size={16}/>);
setSignInStatus('Wait for a moment...');
}
}

const deletePin = () => {


if(pinCount == 2){
setPin(pin.slice(0, -1))
setPinOne(false);
setPinCount(pinCount - 1);
}else if(pinCount == 3){
setPinTwo(false);
setPin(pin.slice(0, -1))
setPinCount(pinCount - 1);
}else if(pinCount == 4){
setPinThree(false);
setPin(pin.slice(0, -1))
setPinCount(pinCount - 1);
}
}

(function(){
if(pin.length == 4){
signin(pin);
}
})()

const isReachable = async () =>{


setIconType(<Ionicons name='swap-vertical-outline' size={20}/>);
setSignInStatus(' Connecting to the server...');
const timeout = new Promise((resolve, reject) => {
setTimeout(reject, 5000, 'Request timed out');
});

const request = fetch('http://119.92.152.243');


try {
const response = await Promise
.race([timeout, request]);
setTimeout(() => {
203
setServerStatus(true);
setIconType('');
setSignInStatus('');
}, 2000);
}
catch (error) {
setServerStatus(false);
setIconType(<Ionicons name='warning' size={20}
color='#F7DC6F'/>);
setSignInStatus(' Please check you internet connection');
}
}

Function called when logging in (React Native Framework):

const signin = async (user_pin) => {


try{
const response = await
fetch('http://119.92.152.243/processes/app_signin.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
pin: user_pin
})
});
const json = await response.json();
if(json == 'offduty'){
setIconType(<Ionicons name='warning' size={16}/>);
setSignInStatus('You are off duty');
reset();
}else if(json == 'unregistered'){
setIconType(<Ionicons name='alert-circle' size={16}/>);
setSignInStatus('Not registered');
reset();
}else if(json == 'error'){
setIconType(<Ionicons name='warning' size={16}/>);
setSignInStatus('Something went wrong');
reset();
}else{
try{
let data = JSON.parse(json);
if(data.status == "onduty"){
setProfilename(data.name);
setProfileURL(data.profile);
setID(data.id);
setBool(true);
reset();
}
}catch(e){
setIconType(<Ionicons name='warning' size={16}/>);
204
setSignInStatus('Something went wrong');
reset();
}
}
}catch(error){
setIconType(<Ionicons name='warning' size={16}/>);
setSignInStatus('Something went wrong');
reset();
}
}

Log in authentication process (PHP):

<?php
require './db_connection.php';
try{
$data = json_decode(file_get_contents('php://input'));
$select_query = $connection->prepare("SELECT ID, OnDuty,
FirstName, LastName, Profile FROM dispatchers WHERE PIN = :pin");
$select_query->bindParam(":pin", $data->pin);
$select_query->execute();
$data_result = $select_query->fetch();
if($data_result == null){
$status = "unregistered";
}elseif(sizeof($data_result) > 0){
if($data_result['OnDuty'] == 1){
$status = json_encode(array("id"=>$data_result['ID'], "status"
=> "onduty", "name" => $data_result['FirstName'] . " " .
$data_result['LastName'], "profile" => $data_result['Profile']));
}else{
$status = "offduty";
}
}
}catch(Exception $e){
$status = "error";
}
echo json_encode($status);
?>

205
2. QR code scanner

QR code scanner using react-native-qrcode-scanner module (React Native Framework):

<QRCodeScanner
onRead = {readingQr}
ref = {(node) => {scanner = node}}
bottomContent = {
<View style={{position: 'relative', width: '100%', height:
350, background: 'green'}}>
<View style={{paddingTop: 20, position: 'absolute',
height: 350, width: '100%', zIndex: 1, alignItems: 'center'}}>
<Text style={{fontWeight: 'bold', fontSize: 18}}>
{status}
</Text>
<TouchableOpacity
style={{
zIndex: 2,
width: 80,
height: 80,
borderRadius: 50,
justifyContent: 'center',
shadowColor: "#000",

206
shadowOffset: {
width: 0,
height: 9,
},
shadowOpacity: 0.50,
shadowRadius: 12.35,
elevation: 19,
overflow: 'hidden'
}}
onPress={reScan}
disabled={botton}
>
<ImageBackground style={{flex: 1, justifyContent:
'center'}} source={buttonColor}>
<Icon
name='qrcode'
type='font-awesome-5'
size={28}
/>
</ImageBackground>
</TouchableOpacity>
</View>
<ImageBackground
style={{flex: 1, opacity: 0.5, zIndex: 0}}
source={require('../assets/gradient_bg.png')}
>
</ImageBackground>
</View>
}
cameraStyle = {{
height: '99.9%'
}}
/>

Function called after scanning and reading QR code’s content (React Native Framework):

const readingQr = (e) => {


if(e.data.match(/ORMOC/) == null){
ws.send('LOADCHANGES');
goodSound.play();
queueVehicle(e.data);
}else{
ws.send('LOADCHANGES');
goodSound.play();
setQRVal(e.data);
setVisible(true);
}
}

Function called if the QR code is PUV (React Native Framework):

207
const queueVehicle = async(data) => {
setStatus('Processing...\n');
setBColor('#2471A3');
try{
const response = await
fetch('http://119.92.152.243/processes/dispatcher_queue_vehicles.php
',{
method: 'POST',
headers:{
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: data
})
});
const json = await response.json();
setBotton(false);
setButtonColor(require('../assets/button_gradient.png'));
setStatus(json + '\n');
if(json == "Vehicle is set to queuing"){
ws.send("LOADCHANGES");
}
}catch(error){
setStatus("Something went wrong\n");
setBotton(false);
setButtonColor(require('../assets/button_gradient.png'));
}
}

Function called if the QR code is passenger (React Native Framework):

const loadPassenger = async(data, destination, companion) => {


try{
const response = await
fetch('http://119.92.152.243/processes/dispatcher_load_passenger.php
', {
method: "POST",
headers:{
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: data,
destination: destination,
companion: companion
})
});
const json = await response.json();
if(json == "waitinglist"){
setStatus("Passenger added to waiting list\n");
}else if(json == "error"){
setStatus("Something went wrong\n");
208
}else{
setStatus("Directly to " + json + "\n");
ws.send("LOADCHANGES");
}
}catch(error){
setBotton(false);
setButtonColor(require('../assets/button_gradient.png'));
setStatus("Something went wrong\n");
}
}

Function called for determining passenger status (React Native Framework):

const checkPassengerStatus = async(data, destination, comp) => {


setStatus('Processing...\n');
setBColor('#2471A3');
try{
const response = await
fetch('http://119.92.152.243/processes/dispatcher_scan_process.php',
{
method: 'POST',
headers:{
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: data,
destination: destination
})
});
const json = await response.json();
setBotton(false);
setButtonColor(require('../assets/button_gradient.png'));
if(json == "clear"){
loadPassenger(data, destination, comp);
}else if(json == "waiting"){
setStatus("Passenger is in waiting list\n");
Alert.alert("Waiting", "Passenger is in waiting list", [
{
text: "Ok"
},
{
text: "Remove",
onPress: () => removePassenger(data, "waiting")
},
{
text: "Load",
onPress: () => loadPassenger(data, destination, comp)
},
],
{
cancelable: true
})
209
}else if(json == "notregistered"){
setStatus("Passenger is not registered\n");
Alert.alert("Not registered", "Passenger's QR is not yet
registered, do you want to register it?",
[
{
text: "Cancel"
},
{
text: "Ok",
onPress: () => setRegVisible(true)
}
])
}else if(json == "error"){
setStatus('Something went wrong\n');
}else{
setStatus("Passenger is already loaded on " + json + "\n");
Alert.alert("Loaded", "Passenger is already loaded on " +
json, [
{
text: "Ok"
},
{
text: "Remove",
onPress: () => removePassenger(data, "loaded")
},
],
{
cancelable: true
})
}
console.log(json);
}catch(error){
setBotton(false);
setButtonColor(require('../assets/button_gradient.png'));
setStatus('Something went wrong\n');
}
}

Process for determining passenger status (PHP):

<?php
require "./db_connection.php";
$data = json_decode(file_get_contents('php://input'));
$qr = $data->data;
$destination = $data->destination;
try{
$find_passenger = $connection->prepare("SELECT COUNT(*) as Count
FROM ormoc_commuters WHERE QR = :qr");
$find_passenger->bindParam(":qr", $qr);
$find_passenger->execute();
$passenger = $find_passenger->fetch();
if($passenger['Count'] > 0){
210
$passenger_loaded = $connection->prepare("SELECT Vehicle FROM
loaded_passengers WHERE QR = :qr");
$passenger_loaded->bindParam(":qr", $qr);
$passenger_loaded->execute();
$is_loaded = $passenger_loaded->fetch();
if($passenger_loaded->rowCount() > 0){
echo json_encode($is_loaded['Vehicle']); //passenger is loaded
--------------------------------------------------------------------
----------------------------
}else{
$passenger_waiting = $connection->prepare("SELECT COUNT(*) as
Count FROM waiting_passengers WHERE QR = :qr");
$passenger_waiting->bindParam(":qr", $qr);
$passenger_waiting->execute();
$is_waiting = $passenger_waiting->fetch();
if($is_waiting['Count'] > 0){
echo json_encode("waiting"); //passenger is waiting
--------------------------------------------------------------------
------------------------
}
else{
echo json_encode("clear"); //passenger is clear
--------------------------------------------------------------------
----------------------------
}
}
}else{
echo json_encode("notregistered"); //passenger is not registered
--------------------------------------------------------------------
---------------
}
}catch(Exception $e){
echo json_encode("error");
}
?>

Process for putting the PUV to queuing list (PHP):

<?php
function decryptor($cipheredtext){
$key = "udWH+XfEbKB44oqM";
$c = base64_decode($cipheredtext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$cipheredtext_raw = substr($c, $ivlen+$sha2len);
$plain_string = openssl_decrypt($cipheredtext_raw, $cipher, $key,
$options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $cipheredtext_raw, $key,
$as_binary=true);
if (hash_equals($hmac, $calcmac))
{
return $plain_string;
211
}
}
$data = json_decode(file_get_contents("php://input"));
try{
$vehicle_info = json_decode(decryptor($data->data));
$plate_no = $vehicle_info->plateno;

$queue_vehicles =
json_decode(file_get_contents('../vehicles/vehicles.json'));
$registered = false;
foreach($queue_vehicles as $vehicle){
if($vehicle->vehicle == $plate_no){
$registered = true;
if($vehicle->queuing == false){
$vehicle->queuing = true;
date_default_timezone_set('Asia/Manila');
$format="%d-%m-%Y_%H:%M:%S";
$strf=strftime($format);
$queuing_list =
json_decode(file_get_contents('../vehicles/queuing_vehicles.json'));
$queuing_info = array("vehicle" => $vehicle->vehicle,
"operator" => $vehicle->operator, "driver" => $vehicle->driver,
"route" => $vehicle->route, "capacity" => $vehicle->capacity,
"passengers" => 0, "time_queue" => $strf);
array_push($queuing_list, $queuing_info);
$altered_queuing_list =
fopen('../vehicles/queuing_vehicles.json', 'w');
$altered_vehicle_list = fopen('../vehicles/vehicles.json',
'w');
fwrite($altered_queuing_list, json_encode($queuing_list));
fwrite($altered_vehicle_list, json_encode($queue_vehicles));
fclose($altered_queuing_list);
fclose($altered_vehicle_list);
echo json_encode("Vehicle is set to queuing");
break;
}elseif($vehicle->queuing == true){
echo json_encode('Vehicle already queuing');
break;
}
}
}
if(!$registered){
echo json_encode("Vehicle is not registered");
}

}catch(Exception $e){
echo json_encode("Something went wrong");
}
?>

Process for assigning passengers with PUV (PHP):

<?php
212
require "./db_connection.php";
$data = json_decode(file_get_contents("php://input"));
$qr = $data->data;
try{
$find_passenger = $connection->prepare("SELECT Contact, Name,
COUNT(*) as Count FROM ormoc_commuters WHERE QR = :qr");
$find_passenger->bindParam(":qr", $qr);
$find_passenger->execute();
$passenger = $find_passenger->fetch();
if($passenger['Count'] > 0){
$passenger_name = $passenger['Name'];
$contact_num = $passenger['Contact'];
$destination = $data->destination;
$companion = $data->companion;
$vehicle_available = false;
$vehicle_not_full = false;
$queuing_vehicles =
json_decode(file_get_contents("../vehicles/queuing_vehicles.json"));
foreach($queuing_vehicles as $vehicle){
if($vehicle->route == $destination){
$vehicle_available = true;
if($vehicle->passengers < $vehicle->capacity){
$vehicle_not_full = true;
$check_if_waiting = $connection->prepare("SELECT
Count(*) as Count FROM waiting_passengers WHERE QR = :qr");
$check_if_waiting->bindParam(":qr", $qr);
$check_if_waiting->execute();
$is_waiting = $check_if_waiting->fetch();
if($is_waiting['Count'] > 0){
$remove_passenger = $connection->prepare("DELETE FROM
waiting_passengers WHERE QR = :qr");
$remove_passenger->bindParam(":qr", $qr);
$remove_passenger->execute();
}
$vehicle->passengers += 1;
$store_passenger = $connection->prepare("INSERT INTO
loaded_passengers(Vehicle, Passenger, QR)
VALUES(:vehicle, :passenger, :qr)");
$store_passenger->bindParam(":vehicle", $vehicle-
>vehicle);
$store_passenger->bindParam(":passenger",
$passenger_name);
$store_passenger->bindParam(":qr", $qr);
$store_passenger->execute();
$vehicle_filename = $vehicle->route . "_" . $vehicle-
>vehicle . ".json";
$vehicle_manifest =
json_decode(file_get_contents("../vehicles/" . $vehicle_filename));
foreach($vehicle_manifest as $vehicle_passenger){
if($vehicle_passenger->Name == "" &&
$vehicle_passenger->Companion == "" && $vehicle_passenger->Number ==
""){
$vehicle_passenger->Name = $passenger_name;
$vehicle_passenger->Companion = $companion; //You
stopped here -> 1 CORINTHIANS 10:31
213
$vehicle_passenger->Number = $contact_num;
break;
}
}
$file_increment_vehicle =
fopen("../vehicles/queuing_vehicles.json", "w");
fwrite($file_increment_vehicle,
json_encode($queuing_vehicles));
fclose($file_increment_vehicle);
$file_add_passenger = fopen("../vehicles/" .
$vehicle_filename, "w");
fwrite($file_add_passenger,
json_encode($vehicle_manifest));
fclose($file_add_passenger);
echo json_encode($vehicle->vehicle);
break;
}
}
}
if(!$vehicle_available || !$vehicle_not_full){
$check_if_waiting = $connection->prepare("SELECT Count(*) as
Count FROM waiting_passengers WHERE QR = :qr");
$check_if_waiting->bindParam(":qr", $qr);
$check_if_waiting->execute();
$is_waiting = $check_if_waiting->fetch();
if($is_waiting['Count'] > 0){
$remove_passenger = $connection->prepare("DELETE FROM
waiting_passengers WHERE QR = :qr");
$remove_passenger->bindParam(":qr", $qr);
$remove_passenger->execute();
}
$load_to_waiting = $connection->prepare("INSERT INTO
waiting_passengers(Destination, Passenger, QR)
VALUES(:destination, :passenger, :qr)");
$load_to_waiting->bindParam(":destination", $destination);
$load_to_waiting->bindParam(":passenger", $passenger_name);
$load_to_waiting->bindParam(":qr", $qr);
$load_to_waiting->execute();
echo json_encode("waitinglist");
}
}
}catch(Exception $e){
echo json_encode("error");
}
?>

Function called for removing passengers from the boarded PUV and waiting list (React Native
Framework):

const removePassenger = async(data, status) => {


try{

214
const response = await
fetch('http://119.92.152.243/processes/dispatcher_remove_passenger.p
hp',{
method: "POST",
headers:{
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: data,
status: status
})
});
const json = await response.json();
if(json == "success"){
ws.send("LOADCHANGES");
setStatus("Passenger removed\n");
Alert.alert("Passenger removed", "Passenger is successfully
removed", [{
text: "Ok"
}],
{
cancelable: true
});
}else if(json == "error"){
setStatus("Something went wrong\n");
Alert.alert("Something went wrong", "Something went wrong,
removing the passenger", [{
text: "Ok"
}],
{
cancelable: true
});
}else{
setStatus("Something went wrong\n");
Alert.alert("Something went wrong", "Something went wrong,
removing the passenger", [{
text: "Ok"
}],
{
cancelable: true
});
}
}catch(error){
setBotton(false);
setButtonColor(require('../assets/button_gradient.png'));
setStatus("Something went wrong\n");
Alert.alert("Something went wrong", "Something went wrong
removing the passenger", {
cancelable: true
});
}
}

215
Process for removing passenger from boarded PUV and waiting list (PHP):

<?php
require "./db_connection.php";
$data = json_decode(file_get_contents("php://input"));
$qr = $data->data;
try{
if($data->status == "loaded"){
$get_passenger = $connection->prepare("SELECT Name FROM
ormoc_commuters WHERE QR = :qr");
$get_passenger->bindParam(":qr", $qr);
$get_passenger->execute();
$passenger = $get_passenger->fetch();
if($get_passenger->rowCount() > 0){
$passenger_name = $passenger['Name'];
$passenger_vehicle = $connection->prepare("SELECT Vehicle FROM
loaded_passengers WHERE QR = :qr");
$passenger_vehicle->bindParam(":qr", $qr);
$passenger_vehicle->execute();
$vehicle = $passenger_vehicle->fetch();
if($passenger_vehicle->rowCount() > 0){
$vehicle_name = $vehicle['Vehicle'];
$remove_query = $connection->prepare("DELETE FROM
loaded_passengers WHERE QR = :qr");
$remove_query->bindParam(":qr", $qr);
$remove_query->execute();
$queuing_vehicles =
json_decode(file_get_contents("../vehicles/queuing_vehicles.json"));
foreach($queuing_vehicles as $vehicle){
if($vehicle->vehicle == $vehicle_name){
$vehicle->passengers = $vehicle->passengers - 1;
$vehicle_name = $vehicle->route . "_" . $vehicle-
>vehicle . ".json";
$vehicle_passenger_list =
json_decode(file_get_contents("../vehicles/" . $vehicle_name));
foreach($vehicle_passenger_list as $passenger){
if($passenger->Name == $passenger_name){
$passenger->Name = "";
$passenger->Companion = "";
$passenger->Number = "";
$queuing_vehicles_file =
fopen("../vehicles/queuing_vehicles.json", "w");
fwrite($queuing_vehicles_file,
json_encode($queuing_vehicles));
fclose($queuing_vehicles_file);
$passengers_file = fopen("../vehicles/" .
$vehicle_name, "w");
fwrite($passengers_file,
json_encode($vehicle_passenger_list));
fclose($passengers_file);
echo json_encode("success");
break;
}
}
216
break;
}
}
}else{
echo json_encode("error");
}
}else{
echo json_encode("error");
}
}else if($data->status == "waiting"){
$remove_waiting_passenger = $connection->prepare("DELETE FROM
waiting_passengers WHERE QR = :qr");
$remove_waiting_passenger->bindParam(":qr", $qr);
$remove_waiting_passenger->execute();
echo json_encode("success");
}

}catch(Exception $e){
echo json_encode("error");
}
?>

3. PUV list

217
Function called for retrieving queuing PUV list (React Native Framework):

const retrieveList = async() => {


try{
const response = await
fetch('http://119.92.152.243/processes/retrievelist.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});
const json = await response.json();
setReply(JSON.parse(json));
}catch(error){
Alert.alert("Problem loading PUVs", "Cannot load currently
queuing PUV, please check your internet connection and try again");
}
finally{
setLoading(false);
}
}

Process retrieving the list of queuing PUVs (PHP):

<?php
$data = file_get_contents('../vehicles/queuing_vehicles.json');
echo json_encode($data);
?>

Function called when pressing the dequeue button for queuing PUV (React Native Framework):

const unqueue = async(data) => {


try{
const response = await
fetch('http://119.92.152.243/processes/dispatcher_unqueue_vehicle.ph
p', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: data
})
});
const json = await response.json();

218
json == "error" ? Alert.alert("Cannot dequeue PUV", "Cannot
dequeue PUV, please check your internet connection and try again") :
unqueueSuccessFunction(json);
}catch(error){
Alert.alert("Cannot dequeue PUV", "Cannot dequeue PUV, please
check your internet connection and try again");
}
}

Process for dequeuing queuing PUVs (PHP):

<?php
require './db_connection.php';
$vehicle = json_decode(file_get_contents('php://input'));
$data = $vehicle->data;
$proceed = true;
try{
$delete_passenger_query = $connection->prepare("DELETE FROM
loaded_passengers WHERE Vehicle = :vehicle");
$delete_passenger_query->bindParam(":vehicle", $data);
$delete_passenger_query->execute();
}catch(Exception $e){
$proceed = false;
}
if($proceed){
$queuing_vehicles_list =
json_decode(file_get_contents('../vehicles/queuing_vehicles.json'));
$count_1 = 0;
$count_2 = 0;
$count_3 = 0;
if(sizeof($queuing_vehicles_list) > 0){
foreach($queuing_vehicles_list as $vehicle){
if($vehicle->vehicle == $data){
$queue_time = $vehicle->time_queue;
array_splice($queuing_vehicles_list, $count_1, 1);
$vehicles_list =
json_decode(file_get_contents('../vehicles/vehicles.json'));
foreach($vehicles_list as $list_of_vehicles){
if($list_of_vehicles->vehicle === $data &&
$list_of_vehicles->queuing === true){
$puv_passengers = $list_of_vehicles->route . "_" .
$list_of_vehicles->vehicle . ".json";
$vehicles_list[$count_2]->queuing = false;
date_default_timezone_set('Asia/Manila');
$format = "%d-%m-%Y_%H:%M:%S";
$strf = strftime($format);
$route = $list_of_vehicles->route;
$directory = "../logs/" . $strf . "_" . $route . "_" .
$list_of_vehicles->vehicle . ".txt";
if(!copy("../vehicles/" . $puv_passengers, $directory)){
echo json_encode("error");
}
else{
219
try{
$puv_passenger_info =
json_decode(file_get_contents("../logs/" . $strf . "_" . $route .
"_" . $list_of_vehicles->vehicle . ".txt"));
array_push($puv_passenger_info, array("queuetime" =>
$queue_time, "leavetime" => $strf));
$altered_puv_passenger_info = fopen("../logs/" .
$strf . "_" . $route . "_" . $list_of_vehicles->vehicle . ".txt",
"w");
fwrite($altered_puv_passenger_info,
json_encode($puv_passenger_info));
fclose($altered_puv_passenger_info);
$passenger_count = 0;
$passenger_list_array =
json_decode(file_get_contents("../vehicles/" . $puv_passengers));
foreach($passenger_list_array as $passenger_name){
if($passenger_name->Name != ""){
$passenger_name->Name = "";
$passenger_name->Companion = "";
$passenger_name->Number = "";
$passenger_count += 1;
}
$count_3 += 1;
}
$passengers = $passenger_count . "/" . $count_3;
$server_directory = "./logs/" . $strf . "_" . $route
. "_" . $list_of_vehicles->vehicle . ".txt";
$save_log_directory = $connection->prepare("INSERT
INTO logs(Directory, Vehicle, Passengers, Route, LogTime, LogDate)
VALUES(:directory, :vehicle, :passengers, :route, now(), now())");
$save_log_directory->bindParam(':directory',
$server_directory);
$save_log_directory->bindParam(':vehicle', $data);
$save_log_directory->bindParam(':passengers',
$passengers);
$save_log_directory->bindParam(':route', $route);
$save_log_directory->execute();
$queuing_vehicles_file =
fopen('../vehicles/queuing_vehicles.json', 'w');
$all_vehicle_file =
fopen('../vehicles/vehicles.json', 'w');
$passenger_list_file = fopen("../vehicles/" .
$puv_passengers, 'w');
fwrite($queuing_vehicles_file,
json_encode($queuing_vehicles_list));
fwrite($all_vehicle_file,
json_encode($vehicles_list));
fwrite($passenger_list_file,
json_encode($passenger_list_array));
fclose($queuing_vehicles_file);
fclose($all_vehicle_file);
fclose($passenger_list_file);
echo
json_encode(json_encode($queuing_vehicles_list));
break;
220
}catch(Exception $e){
echo json_encode("error");
}
}
}
$count_2 += 1;
}
break;
}
$count_1 += 1;
}
}
}
else{
echo json_encode("error");
}

4. Passenger list

Function called for retrieving the list of passengers that boarded to each queuing PUVs (React Native
Framework):
221
const retrievePassengerList = async(data) => {
try{
const response = await
fetch('http://119.92.152.243/processes/retrievepassengerlist.php',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: data
})
});
const json = await response.json();
setReply(JSON.parse(json));
}catch(error){
Alert.alert("Problem loading passengers", "Cannot load
passengers, please check your internet connection and try again");
}finally{
setLoading(false);
}
}

Process for retrieving passenger list (PHP):

<?php
$request = file_get_contents("php://input");
$data = json_decode($request);
$reply = file_get_contents("../vehicles/" . $data->data);
echo json_encode($reply);
?>

Function called for removing passenger from boarded PUV (React Native Framework):

const unload = async(file, passenger, vehicle) => {


try{
const response = await
fetch('http://119.92.152.243/processes/unload.php',{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
file: file,
passenger: passenger,
vehicle: vehicle
})
});
const json = await response.json();

222
if(json == 'error'){
Alert.alert("Something went wrong", "The passenger was not
successfully unloaded");
}else{
try{
setReply(JSON.parse(json));
setPassengerCount(passengerCount - 1);
}catch(e){
Alert.alert("Something went wrong", "The passenger was not
successfully unloaded");
}
}
}catch(error){
Alert.alert("Something went wrong", "The passenger was not
successfully unloaded");
}
}

Process for removing passenger from boarded PUV (PHP):

<?php
require "./db_connection.php";
$data = json_decode(file_get_contents("php://input"));
try{
$passenger_name = json_decode(file_get_contents("../vehicles/" .
$data->file));
foreach($passenger_name as $passenger){
if($passenger->Name == $data->passenger){
$passenger->Name = "";
$passenger->Companion = "";
$passenger->Number = "";
$queuing_vehicles =
json_decode(file_get_contents("../vehicles/queuing_vehicles.json"));
foreach($queuing_vehicles as $vehicle){
if($vehicle->vehicle == $data->vehicle){
$vehicle->passengers = $vehicle->passengers - 1;
$delete_the_passenger = $connection->prepare("DELETE FROM
loaded_passengers WHERE Passenger = :passenger AND Vehicle
= :vehicle");
$delete_the_passenger->bindParam(":passenger", $data-
>passenger);
$delete_the_passenger->bindParam(":vehicle", $data-
>vehicle);
$delete_the_passenger->execute();
$passenger_file = fopen("../vehicles/" . $data->file,
"w");
fwrite($passenger_file, json_encode($passenger_name));
fclose($passenger_file);
$vehicle_file = fopen("../vehicles/queuing_vehicles.json",
"w");
fwrite($vehicle_file, json_encode($queuing_vehicles));
fclose($vehicle_file);
echo json_encode(json_encode($passenger_name));
223
break;
}
}
break;
}
}
}catch(Exception $e){
echo "error";
}
$connection = null;
?>

5. Manual queuing

224
Function called for loading passenger to PUV using manual queuing (React Native Framework):

const loadPassenger = async(data, name, destination, comp, num) => {


console.log(data + name + destination + comp);
try{
const response = await
fetch('http://119.92.152.243/processes/dispatcher_manual_queue.php',
{
method: 'POST',
headers:{
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: data,
name: name,
destination: destination,
companion: comp,
number: num
})
});
const json = await response.json();
if(json == "error"){
setStatus("Something went wrong");
}else{
setStatus(json);
ws.send("LOADCHANGES");
reset();
}
}catch(error){
setStatus('Something went wrong');
console.log(error);
}
}

Process for loading passenger to PUV using manual queuing (PHP):

<?php
require "./db_connection.php";
$data = json_decode(file_get_contents("php://input"));
try{
$queuing_vehicles =
json_decode(file_get_contents("../vehicles/queuing_vehicles.json"));
$vehicle_not_full = false;
$vehicle_available = false;
foreach($queuing_vehicles as $vehicle){
if($vehicle->route == $data->destination){
$vehicle_available = true;
if($vehicle->passengers < $vehicle->capacity){

225
$vehicle_not_full = true;
$vehicle->passengers = $vehicle->passengers + 1;
$write_the_passenger =
json_decode(file_get_contents("../vehicles/" . $vehicle->route . "_"
. $vehicle->vehicle . ".json"));
foreach($write_the_passenger as $passenger_name){
if($passenger_name->Name == "" && $passenger_name-
>Companion == "" && $passenger_name->Number == ""){
$passenger_name->Number = $data->number;
$passenger_name->Name = $data->name;
$passenger_name->Companion = $data->companion;
$load_passenger = $connection->prepare("INSERT INTO
loaded_passengers(Vehicle, Passenger, QR)
VALUES(:vehicle, :passenger, :qr)");
$load_passenger->bindParam(":vehicle", $vehicle-
>vehicle);
$load_passenger->bindParam(":passenger", $data->name);
$load_passenger->bindParam(":qr", $data->data);
$load_passenger->execute();
$vehicle_file =
fopen("../vehicles/queuing_vehicles.json", "w");
fwrite($vehicle_file, json_encode($queuing_vehicles));
fclose($vehicle_file);
$passenger_file = fopen("../vehicles/" . $vehicle->route
. "_" . $vehicle->vehicle . ".json", "w");
fwrite($passenger_file,
json_encode($write_the_passenger));
fclose($passenger_file);
echo json_encode("Go directly to " . $vehicle->vehicle);
break;
}
}
}
break;
}
}
if($vehicle_not_full == false && $vehicle_available == false){
echo json_encode("PUV is not available");
}
}catch(Exception $e){
echo json_encode("error");
}
?>

226
6. Dispatcher’s profile

When pressing the log-out button (React Native Framework):

onPress = {() => {


setBool(false);
setSignInStatus('');
setIconType('');
}}

Passenger’s Mobile Application

1. Passenger’s QR code list

227
Function for retrieving stored QR code (React Native Framework):

const getData = async() => {


try{
const value = await AsyncStorage.getItem('@qr_uri');
if(value != null){
setQRURI(JSON.parse(value));
}
}catch(e){
Alert.alert("Something went wrong", "Encountered an error
retrieving your registered QR")
}
}

Function for storing QR code (React Native Framework):

const storeData = async(value, bool) => {


try{
if(bool){
qruri.push(value);
}
await AsyncStorage.setItem('@qr_uri', JSON.stringify(qruri));
}catch(e){
Alert.alert("Something went wrong", "Encountered an error saving
the qr image")
}
}

React Native components for display QR code images (React Native Framework):
228
const QRs = ({item, index, remove}) => (
<View
style={{
borderRadius: 5,
justifyContent: "center",
alignItems: "center",
marginVertical: 5,
marginHorizontal: 10,
position: 'relative',
overflow: 'hidden',
flex: 1,
}}
>
<ImageBackground
source={require('../assets/qr_card_background.jpg')}
style={{flex: 1, height: '100%', width: '100%', position:
'absolute', opacity: 0.7}}>
</ImageBackground>
<TouchableOpacity
style={{
alignSelf: 'flex-end'
}}
onPress={() => {
Alert.alert("Delete QR?", "QR will be unregistered and will be
remove in this device", [
{
text: "Cancel",
style: "cancel"
},
{
text: "Ok",
onPress: () => {
remove(index, item.code);
}
}
]);
}}
delayLongPress={1000}
>
<Ionicons name="remove-circle" size={40} color="#C0392B"/>
</TouchableOpacity>
<View>
<ImageModal
resizeMode="contain"
imageBackgroundColor="#000000"
style={{
width: 300,
height: 300,
borderRadius: 5
}}
source={{
uri: item.uri,
}}
/>
</View>
229
<View style={{
marginTop: 20,
marginBottom: 20,
textAlign: 'center',
}}>
<Text style={{
alignSelf: "center",
fontSize: 23,
fontWeight: "bold",
color: 'white'
}}>
{item.fullname}
</Text>
</View>
</View>
)

2. Registering QR code using mobile phone’s camera

QR code scanner using react-native-qr-code module (React Native Framework):

<QRCodeScanner
cameraStyle={{
230
height: '100%'
}}
onRead={retrievedData}
ref={(node) => {scanner = node}}
bottomContent={
<View style={{position: 'relative', width: '100%',
height: 350, background: 'green'}}>
<View style={{paddingTop: 20, position: 'absolute',
height: 350, width: '100%', zIndex: 1, alignItems: 'center'}}>
<Text style={{fontWeight: 'bold', fontSize: 18}}>
</Text>
<TouchableOpacity
style={{
zIndex: 2,
width: 80,
height: 80,
borderRadius: 50,
justifyContent: 'center',
overflow: 'hidden'
}}
onPress={reScan}
>
<View style={{flex: 1, justifyContent: 'center'}}>
<Ionicons name='ios-radio-button-on' size={84}
color={bgcolor}/>
</View>
</TouchableOpacity>
</View>
<ImageBackground
style={{flex: 1, opacity: 0.5, zIndex: 0}}
source={require('../assets/gradient_bg.png')}
>
</ImageBackground>
</View>
}
/>

Function called when QR code content is scanned and read (React Native Framework):

const retrievedData = (e) => {


if(e.data.match(/ORMOC/) == null){
Alert.alert("QR is not recognized", "Please use a valid QR
image");
setReScan(true);
setBgColor('white');
}
else{
navigation.navigate('QRs', {QRdata: e.data});
}
}

Function called for registering QR code (React Native Framework):

231
const checkInfo = async () => {
if(qruri.length < 3){
if (fname.trim() === '' || mname.trim() === '' || lname.trim()
=== '' || cnum.trim() === '') {
Alert.alert("Missing fields", "Please fill all the field",
[{text: "Ok", onPress: () => setLoading('none')}]);
}else if(cnum.trim().length != 11){
setLoading('none');
Alert.alert("Invalid input", "Contact number dit not meet the
amount of numbers required", [{text: "Ok", onPress: () =>
setLoading('none')}]);
}else if(qrval == ''){
Alert.alert("Error", "No QR code scanned", [{text: "Ok",
onPress: () => setLoading('none')}]);
}else{
let invalid_char = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;
if(invalid_char.test(fname.trim()) ||
invalid_char.test(mname.trim()) || invalid_char.test(lname.trim())){
Alert.alert("Invalid input", "Special characters are not
allowed e.g. (dot, comma, numbers, etc.)", [{text: "Ok", onPress: ()
=> setLoading('none')}]);
}else{
let invalid_str = /\d/;
if(invalid_str.test(fname.trim()) ||
invalid_str.test(mname.trim()) || invalid_str.test(lname.trim())){
Alert.alert("Invalid input", "Special characters are not
allowed e.g. (dot, comma, numbers, etc.)", [{text: "Ok", onPress: ()
=> setLoading('none')}]);
}else{
let fullname = fname.trim() + ' ' + mname.trim() + ' ' +
lname.trim();
let contact = cnum;
try{
const response = await
fetch('http://119.92.152.243/processes/passenger_register_qr.php', {
method: 'POST',
headers:{
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
fullname: makeItCorrect(fullname),
contact: contact,
qr: qrval
})
});
const json = await response.json();
if(json == 'success'){
RNQRGenerator.generate({
value: qrval,
height: 100,
width: 100,
}).then(response => {
const {uri} = response;

232
storeData({uri: uri, fullname:
makeItCorrect(fullname), code: qrval}, true);
setVisible(false);
setFname('');
setMname('');
setLname('');
setCnum('');
setLoading('none');
}).catch(error => {
Alert.alert("Error saving QR", "QR cannot be stored
but is successfully registered", [{text: "Ok", onPress: () =>
setLoading('none')}])
});
}else if(json == 'registered'){
Alert.alert("QR is already registered", "You might
have not properly removed this QR. You can still use the digital or
physical QR code if you still have it.", [{text: "Ok", onPress: ()
=> setLoading('none')}])
}else if(json == 'error'){
Alert.alert("Something went wrong", "This is maybe in
our side, we are going to work on it", [{text: "Ok", onPress: () =>
setLoading('none')}]);
}else{
Alert.alert("Something went wrong", "This is maybe in
our side, we are going to work on it", [{text: "Ok", onPress: () =>
setLoading('none')}]);
}
}catch(error){
Alert.alert("Something went wrong", "This is maybe in
our side, we are going to work on it", [{text: "Ok", onPress: () =>
setLoading('none')}]);
}
}
}
}
}else{
Alert.alert("QR limit exceed", "You are only allowed to register
three QR codes in one device", [{text: "Ok", onPress: () =>
setLoading('none')}]);
}
}

QR code registration process (PHP):

<?php
$data = json_decode(file_get_contents('php://input'));
if(!empty(trim($data->fullname)) && !empty(trim($data->contact))
&& !empty(trim($data->qr))){
require './db_connection.php';
$fullname = $data->fullname;
$contact = $data->contact;
$qr = $data->qr;
try{
233
$check_redundancy = $connection->prepare("SELECT * FROM
ormoc_commuters WHERE QR = :qr");
$check_redundancy->bindParam(":qr", $qr);
$check_redundancy->execute();
$passenger = $check_redundancy->rowCount();
if($passenger > 0){
echo json_encode('registered');
}else{
$register_passenger = $connection->prepare("INSERT INTO
ormoc_commuters(QR, Name, Contact)
VALUES(:qr, :fullname, :contact)");
$register_passenger->bindParam(":qr", $qr);
$register_passenger->bindParam(":fullname", $fullname);
$register_passenger->bindParam(":contact", $contact);
$register_passenger->execute();
echo json_encode('success');
}
}catch(Exception $e){
echo json_encode('error');
}
}else{
echo json_encode('error');
}
?>

Function called when removing QR code (React Native Framework):

const remove = async (i, code) => {


try{
const response = await
fetch('http://119.92.152.243/processes/passenger_unregister_qr.php',
{
method: 'POST',
headers:{
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
qrcode: code
})
});
const json = await response.json();
if(json == 'success'){
qruri.splice(i, 1);
storeData('', false);
getData();
Alert.alert("QR was successfully removed", "Please be careful
on clearing the application's data without ensuring that QRs are
properly removed using the application. Once QR is not properly
removed using the application, it will not be registered again
because the data is still stored in the database. We restrict the
retrieval of stored data because it violates privacy and security of
the user.")
234
}else if(json == 'notfound'){
Alert.alert("Something is wrong", "You have the QR on you
phone but not in our database");
}else if(json == 'error'){
Alert.alert("Something went wrong", "This is maybe in our
side, we are going to work on it");
}else{
Alert.alert("Something went wrong", "This is maybe in our
side, we are going to work on it");
}
}catch(error){
Alert.alert("Something went wrong", "This is maybe in our side,
we are going to work on it");
}
}

Unregistering passenger’s QR process (React Native Framework):

<?php
$data = json_decode(file_get_contents('php://input'));
if(!empty(trim($data->qrcode))){
require './db_connection.php';
$qrcode = $data->qrcode;
try{
$check_existance = $connection->prepare("SELECT * FROM
ormoc_commuters WHERE QR = :qr");
$check_existance->bindParam(":qr", $qrcode);
$check_existance->execute();
$passenger = $check_existance->fetchColumn();
if($passenger > 0){
$remove_passenger = $connection->prepare("DELETE FROM
ormoc_commuters WHERE QR = :qr");
$remove_passenger->bindParam(":qr", $qrcode);
$remove_passenger->execute();
echo json_encode('success');
}else{
echo json_encode('notfound');
}
}catch(Exception $e){
echo json_encode('error');
}
}else{
echo json_encode('error');
}
?>

235
3. Registering passenger’s QR code using react-native-picker and image gallery.

Function called when QR code image content is scanned and read (React Native Framework):

const scanImage = () => {


launchImageLibrary({}, response => {
if(!response.didCancel){
const {assets} = response;
const [items] = assets;
const {uri} = items;
RNQRGenerator.detect({
uri: uri
}).then(response => {
const {values} = response;
const [qrvalue] = values;
if(qrvalue == null){
Alert.alert("Invalid file", "File is not recognized");
}
236
else{
if(qrvalue.match(/ORMOC/) == null){
Alert.alert("Invalid QR", "QR code is not valid");
}
else{
setQRVal(qrvalue);
setVisible(true);
}
}
}).catch(error => Alert.alert("Something went wrong", "An
unexpected error was encountered while scanning the QR image"));
}
})
}

4. Queuing PUV list

Functions called for each queuing PUVs’ destination (React Native Framework):

const valencia = ({navigation}) => {


return(
<QueuingPUVs
destination = 'valencia'
navigation = {navigation}

237
/>
);
}

const puertobello = ({navigation}) => {


return(
<QueuingPUVs
destination = 'puertobello'
navigation = {navigation}
/>
);
}

const albuera = ({navigation}) => {


return(
<QueuingPUVs
destination = 'albuera'
navigation = {navigation}
/>
);
}

const sabangbao = ({navigation}) => {


return(
<QueuingPUVs
destination = 'sabangbao'
navigation = {navigation}
/>
);
}

Function called for retrieving queuing PUVs (React Native Framework):

const getPUVList = async () => {


try{
const response = await
fetch('http://119.92.152.243/processes/get_queuing_vehicles.php',{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: destination
})
});
const json = await response.json();
setPUVList(JSON.parse(json));
}catch(error){
Alert.alert('Error loading PUVs', 'Please check your internet
connection and try again');
}finally{
setLoading(false);
238
}
}

Process for retrieving queuing PUV list (PHP):

<?php

$data = json_decode(file_get_contents('php://input'));
$queuing_vehicles =
json_decode(file_get_contents('../vehicles/queuing_vehicles.json'));
$vehicle_queuing = array();

foreach ($queuing_vehicles as $vehicle) {


if($vehicle->route == $data->data){
array_push($vehicle_queuing, array("Vehicle" => $vehicle-
>vehicle, "Passengers" => $vehicle->passengers, "Capacity" =>
$vehicle->capacity));
}
}

echo json_encode(json_encode($vehicle_queuing));
?>

5. Returning PUV list

239
Function called for each returning PUVs destination (React Native Framework)

const returningValencia = ({navigation}) => {


return(
<ReturningPUV
destination = 'valencia'
navigation = {navigation}
/>
);
}

const returningPuertobello = ({navigation}) => {


return(
<ReturningPUV
destination = 'puertobello'
navigation = {navigation}
/>
);
}

const returningAlbuera = ({navigation}) => {


return(
<ReturningPUV
destination = 'albuera'
navigation = {navigation}
/>
);
}

const returningSabangBao = ({navigation}) => {


return(
<ReturningPUV
destination = 'sabangbao'
navigation = {navigation}
/>
);
}

Function called for retrieving returning PUV list (React Native Framework):

const getPUVList = async () => {


try{
const response = await
fetch('http://119.92.152.243/processes/retrieve_returning_puv.php',{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: destination
})

240
});
const json = await response.json();
setPUVList(JSON.parse(json));
}catch(error){
Alert.alert('Error loading PUVs', 'Please check your internet
connection and try again');
}finally{
setLoading(false);
}
}

Process for retrieving returning PUV list (PHP):

<?php
$data = json_decode(file_get_contents('php://input'));
$vehicles =
json_decode(file_get_contents('../vehicles/vehicles.json'));
$returning_vehicles = [];

foreach($vehicles as $vehicle){
if($vehicle->route == $data->data && $vehicle->returning){
array_push($returning_vehicles, array("Vehicle" => $vehicle-
>vehicle, "Capacity" => $vehicle->capacity));
}
}

echo json_encode(json_encode($returning_vehicles));

?>

241
Appendix J

Date:__________________

GRAMMARIAN’S CERTIFICATE

This is to certify that the undersigned has reviewed and went through all the pages of the

proposed project study/research entitled “Web-based Public Utility Vehicle10/12/2021


and Passenger

Queuing Management System for Ormoc City Public Utility Vehicle Terminal: A Proposed

Passenger Assistance System with Mobile Application”. As against the set of structural rules that

governs the composition of sentences, phrases, and words in the English language.

Signed,

MARIA QUEENNA D. MOSQUITO


Signature over Printed Name

Conformed:

JOELITO Q. CAORTE JANCARLO S. DOYON


Signature over Printed Name Signature over Printed Name
Student Student

JOHN CARLO L. VILLAS


Signature over242
Printed Name
Student

You might also like