Code Manual

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 17

DownloadCode Manual
Open PDF In BrowserView PDF
Scavenger Hunt User Manual

This document is intended for the use of maintenance and update of the Montgomery County
Scavenger Hunt.
Map:
1. map = new Map("map", {
2. //you may change the basemap here
3.
basemap: "streets-vector",
4.
zoom: 16,
5.
slider: false
6. });

Change or add the map attributes here.

Layer:
1. //add layer
2. var agoServiceURL = "http://montgomeryplans.org/arcgis4/rest/services/Overlays/M
CAtlas_Park_Information/MapServer";
3. var agoLayer = new ArcGISTiledMapServiceLayer(agoServiceURL);
4. map.addLayer(agoLayer);

Change the layer or lay URL

Point of interest on the map (one example)

Connect to the database and check if the user has already been to this point of interest.
The query returns one row which means this user has been to this point of interest (point no.1
in this case). Set the color variable to grey.
If it returns not one row, the user has not been to this point of interest. Set the color variable to
red.
Create symbol variable.
Set symbol attribute – the information of site 1.
Set geolocation for this symbol.
Add this symbol to the map with its site info, color, shape, and geolocation.
The rest of points of interest marks follow the same logic.

1.

//adding points of interest on the map, there are 92 of them, the code are repe
ative with different geolocation info for each point
2. //before adding the points, check if the user has been to this point. If YES, s
et color of the point to grey, if No, set color of point to red
3. //refer the park info document to see the list of site names, their info and th
eir ID, the table sites in the database is also help but not comprehensvie
4.
5. //very first point
6.
7.

31.
//use function to add point "1" to the map
32.
function addPointGraphics(){
33.
34.
let color = new Color ()
35.
let color2 = new Color ()
36.
let symbol = new SimpleMarkerSymbol (SimpleMarkerSymbol.STYLE_CIRCL
E, 9,
37.
new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, color,9), color
2);
38.
//set the site info
39.
let attr = {"site name": "\"A Dahlia Garden\"", "park name":"Agricu
ltural History Farm Park", "compass coordinates":"39 9\'51\"N 77 8\'2\"W", lat:
-77.132439, long: 39.165291} ;
40.
//mark this site to the following geolocation
41.
let loc= new Point(-77.132439, 39.165291);
42.
43.
let graphic = new Graphic(loc, symbol, attr, infoTemplate);

44.
45.
map.graphics.add(graphic);
46.
47.
}
48.
map.on("load", addPointGraphics);
49.
50.
51.
52. //end first

Question forms
Each site has two questions for users upon arrival.
By default, questions are hidden by CSS class.
When user arrives, the first question pops up.
The users are mandatory to choose an answer out of four choices. If they don’t, they receive a
hint for correction.
The users have infinite opportunities to find out the right answer. Each wrong attempt will
result a hint for correction.
The answer input with value 1 is the right answer.
After passing the first question, the first question is hidden, and the second question pops up.
Some logic applies to the second question regarding the answer verification.
After passing the second question, the second question is hidden as well. All done.
All the questions for the 92 sites follow the same logic.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.







User’s geolocation and the comparison against all the 92 sites.
Var global variables lat and long to store user’s updated geolocation.
Var global variables lat4Decimals and long4Decimals to store user’ updated geolocation as 4
decimals numbers without rounding those numbers.
Compare user’s geolocation against 92 sites by calling the “compare[site number]” function
every 5 seconds. The following only shows 8 of them as demonstration.

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.

var
var
var
var

lat;
long;
lat4Decimals;
long4Decimals;

window.onload=function(){
getLocation();
}
var x = document.getElementById("demo");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.watchPosition(showPosition);
} else {

15.
x.innerHTML = "Geolocation is not supported by this browser.";}
16.
}
17.
18. function showPosition(position) {
19.
x.innerHTML="Current Latitude: " + position.coords.latitude +
20.
"
Current Longitude: " + position.coords.longitude; 21. lat = position.coords.latitude; 22. long = position.coords.longitude; 23. //trim lat and long down to 4 deciamls without rounding 24. lat4Decimals = lat.toString().match(/^-?\d+(?:\.\d{0,4})?/)[0]; 25. long4Decimals = long.toString().match(/^-?\d+(?:\.\d{0,4})?/)[0]; 26. 27. //run functions that compare user's current geolocaton against all 92 every 5 se conds 28. setInterval(compare1,5000); 29. setInterval(compare2,5000); 30. setInterval(compare3,5000); 31. setInterval(compare4,5000); 32. setInterval(compare5,5000); 33. setInterval(compare6,5000); 34. setInterval(compare7,5000); 35. setInterval(compare8,5000); compare user’s geolocation against site 1’s geolocation. Site 1’s geolocation is 39.1652, -76.1324. It is hardcoded into the function. When matches, insert this instance to the table visits in database by calling the “post[site number]” function. 1. //compare the user's geolcation against site 1's geolocation. 2. function compare1() 3. 4. 5. { 6. if (lat4Decimals == 39.1652 && long4Decimals == -77.1324) 7. 8. { 9. //if they match, insert to the database - this user has arrived at site 1 10. post1(); 11. } 12. } Calling “insert.php” in AJAX to insert this instance (this user has arrived at site 1). 1. //insert to the database using AJAX, get "data" back from the php('form' filed i n sql), the value is 0. 0 means user has not answer the question form yet. 2. function post1(){ 3. var userID = ""; 4. $.ajax({ 5. url: 'insert.php', 6. type: 'POST', 7. data:{ 8. userId: userID, 9. // site 1 10. placeId: 1 11. }, 12. success: function(data) { 13. //take value 0 in the function, the function sees 0, then dispaly the questio n form for site 1 14. showme1(data); 15. }, 16. error: function(XMLHttpRequest, textStatus, errorThrown) { 17. // handle any network/server errors here 18. console.log("Status: " + textStatus); 19. console.log("Error: " + errorThrown); 20. } 21. }); 22. } 23. The “insert.php” insets the instance and it also returns the value of the “form” field. By default, the value is 0. The value is stored in variable “check” This value controls if the user has answered the questions for site 1. By having default 0, it figures the user has no answered, so it will pop-up the questions for site 1. After the user passing all the questions, the value will be update to 1, so the questions for site 1 will neve pop- up again for this user. 1. escape_string($_POST['userId']); // current_user_id 6. $placeId = $dbc->escape_string($_POST['placeId']); // the_place_id 7. 8. 9. $sql = "SELECT user_id, site_id FROM visits where (user_id = '".$userId."' and site_id = '". $placeId."')"; 10. $result1 = @mysqli_query ($dbc, $sql); 11. 12. if ( $result1->num_rows == 0 ) { 13. 14. 15. $query = "INSERT INTO visits (user_id, site_id, date) VALUES ('".$userId."' , '".$placeId."', CURRENT_TIMESTAMP())"; 16. 17. 18. $result = @mysqli_query ($dbc, $query); // Run the query. 19. 20. if ($result) { // If it ran OK. 21. // Print a message. 22. echo '

Success!

'; 23. } 24. else { // If it did not run OK. 25. // Print error. 26. echo '

Error

'; 27. }}; 28. 29. 30. 31. 32. $query2 = " 33. SELECT form FROM sites as tp 34. JOIN visits as up ON 35. tp.site_id = up.site_id where (up.user_id = '".$userId."' and tp.site_id = '".$placeId."')" ; 36. $sql2 = mysqli_query($dbc, $query2); 37. if (!$sql2) { 38. printf("Error: %s\n", mysqli_error($dbc)); 39. exit(); 40. } 41. while($row = mysqli_fetch_array($sql2, MYSQLI_AS SOC)) { 42. 43. if ($row['form'] == '0'){ 44. $check = '0'; 45. // echo '

Success f or check 0

';; 46. 47. break; 48. } 49. else { 50. 51. $check = '1'; 52. ; 53. 54. break;} 55. 56. } 57. 58. echo $check; 59. 60. ?> If the value “check” is 0, it finds the questions’ ID number (Q1 in this case). Then displaying the first question by changing CSS attribute. 1. //dispaly question form 2. unction showme1(check){ 3. 4. if(parseInt(check) == 0) 5. { 6. var modal = document.getElementById('Q1'); 7. modal.style.display = "block"; 8. 9. } 10. 11. else { var modal = document.getElementById('Q1'); 12. modal.style.display = "none"} 13. 14. check the first question, if the user chooses the right answer (value = 1), then displays the second question. Check the second question, if the user chooses the right answer, call the function “update[site numer]”. 1. //check user's answer for question 1 2. function validateForm1q1() { 3. var radios = document.getElementsByName("yesno"); 4. var formValid = false; 5. 6. var selectedVal = ""; 7. var selected = $("input[type='radio'][name='yesno']:checked"); 8. selectedVal = selected.val(); 9. 10. var i = 0; 11. while (!formValid && i < radios.length) { 12. if (radios[i].checked) formValid = true; 13. i++; 14. } 15. 16. 17. if (!formValid) 18. { 19. 20. document.getElementById("inputerror1.1").innerHTML = " Must select an option!"; 21. return formValid; 22. } 23. 24. 25. else if (selectedVal!= '1') 26. 27. document.getElementById("inputerror1.1").innerHTML = " Wrong answer, please try again!"; 28. else { 29. 30. //show question 2 after checking 31. next_step1(); 32. } 33. 34. } 35. 36. 37. //show question 2 after checking 38. function next_step1() { 39. document.getElementById("Q1.1").style.display = "none"; 40. document.getElementById("Q1.2").style.display = "block"; 41. 42. } 43. 44. 45. 46. 47. 48. //check user's answer for question 2 49. function validateForm1q2() { 50. var radios = document.getElementsByName("yesno2"); 51. var formValid = false; 52. 53. var selectedVal = ""; 54. var selected = $("input[type='radio'][name='yesno2']:checked"); 55. selectedVal = selected.val(); 56. 57. var i = 0; 58. while (!formValid && i < radios.length) { 59. if (radios[i].checked) formValid = true; 60. i++; 61. } 62. 63. 64. if (!formValid) 65. { 66. document.getElementById("inputerror1.2").innerHTML = "Must select an option!"; 67. 68. return formValid; 69. } 70. 71. 72. else if (selectedVal!= '1') 73. document.getElementById("inputerror1.2").innerHTML = "Wrong answer, please try again!"; 74. 75. else { 76. //update 'from' filed from 0 to 1 in database. User has answered the site 1 questions, it wont show again 77. update1(); 78. } 79. 80. } 81. Call update1.php in update1 function. 1. 2. //update 'from' filed from 0 to 1 in database. User has answered the site 1 que stions, it wont show again 3. function update1(){ 4. 5. var userID = ""; 6. 7. $.ajax({ 8. url: 'update1.php', 9. type: 'POST', 10. data:{ 11. userId: userID, 12. placeId: 1 13. }, 14. success: function(serverResponse) { 15. // handle output from server here ('Success!' or 'Error' from PHP scr ipt) 16. console.log("Successful"); 17. }, 18. error: function(XMLHttpRequest, textStatus, errorThrown) { 19. // handle any network/server errors here 20. console.log("Status: " + textStatus); 21. console.log("Error: " + errorThrown); 22. } 23. }); 24. window.location.reload(); 25. } 26. 27. 28. 29. //end of insert/update site 1 info The Update1.php does: Update the “form” field value from 0 to 1 for this user and for this site in visits table. So, the pop-up questions won’t be displayed again when this user revisits this site in future. Update the “site_score” value from 0 to 1 for this user and for this site in visits table. Check if the user has completed all the sites within each park. If the user has finished all the sites in a park. Update “park_score” value from 0 to 3 for this user and for this park. This update happens only on one of the site visit record that associated to the park. Check if the user has completed all the sites within each division. If the user has finished all the sites in a division. Update “division_score” value from 0 to 25 for this user and for this division. This update happens only on one of the site visit record that associated to the division. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. //update form file from 0 to 1 for this site. no more questions $query = "UPDATE visits SET form = '1' WHERE user_id = '".$userId."' and site_id = '".$placeId."'"; $result = @mysqli_query ($dbc, $query); if ($result) { // If it ran OK. // Print a message. echo '

Success!

'; } else { // If it did not run OK. // Print error. echo '

Error

'; } // update site piont from 0 to 1 for this site $query2 = "UPDATE visits SET site_point = '1' WHERE user_id = '".$userId."' and site_id = '".$placeId."'"; $result2 = @mysqli_query ($dbc, $query2); if ($result2) { // If it ran OK. // Print a message. echo '

Success!

'; } else { // If it did not run OK. // Print error. echo '

Error

'; } /* */ /*if the user has finished all the 5 sites in Agricultural History Farm Park, up date park_point from 0 to 3 on site_id 1, site_id 1 is one of the site in Agricu ltural History Farm Park*/ $query3 = "SELECT COUNT(visits.site_id) from visits join sites on visits.site_id = sites.site_id where user_id = '".$userId."' and park_name = 'Agricultural His tory Farm Park'" ; $result = mysqli_query($dbc, $query3); $row = mysqli_fetch_assoc($result); if ($row['COUNT(visits.site_id)'] == '5') ' 50. 51. 52. 53. extra points { $query4 = "update visits SET park_point = '3' where user_id = '".$userId." and site_id = '1'"; mysqli_query($dbc, $query4);} 54. 55. /*if the user has finished all the 49 sites in north division, update division_p oint from 0 to 25 on site_id 79, site_id 79 is one of the site in north division */ 56. $query3 = "SELECT COUNT(visits.site_id) from visits join sites on visits.site_id = sites.site_id where user_id = '".$userId."' and division_name = 'north'" ;/* divsion name */ 57. $result = mysqli_query($dbc, $query3); 58. $row = mysqli_fetch_assoc($result); 59. if ($row['COUNT(visits.site_id)'] == '49') /* number of sites * / 60. 61. 62. { $query4 = "update visits SET division_point = '25' where user_id = '".$use rId."' and site_id = '79'"; /* site id */ 63. mysqli_query($dbc, $query4);} Leaderboard. The leaderboard.php does: 1. Calculates and displays current user’s score. 2. Displays the top 5 scores and the associate users. Users’ scores can tie. Achievenments A visited point of interest will have a checked mark, and a not yet visited points of interest will have an unchecked mark. 1. $query = "SELECT site_id FROM visits where user_id = '".$user."' order by site_i d" ; 2. 3. $sql = mysqli_query($dbc, $query); 4. $rowcount=mysqli_num_rows($sql); 5. if (!$sql) { 6. printf("Error: %s\n", mysqli_error($dbc)); 7. exit(); 8. } 9. for ( $i= 1; $row = mysqli_fetch_array($sql, MYSQLI_ASSO C); ++$i) 10. { 11. 12. if ($row['site_id'] == '26') 13. { 14. echo ""; break;} 15. else if ($i == $rowcount) 16. echo ""; 17. }?> 18. Fraction number is used to indicate how many points of interest in a park the user has visited versus the total number of points of interest in that particular park. 1. $query = "SELECT count(visits.site_id) FROM visits 2. JOIN sites on sites.site_id = visits.site_id 3. where user_id = '".$user."' and park_name = 'Agricultural History Farm Park'" ; 4. 5. $query1 = "SELECT count(site_id) FROM sites 6. where park_name = 'Agricultural History Farm Park'" ; 7. 8. 9. 10. $result = mysqli_query($dbc, $query); 11. $row = mysqli_fetch_assoc($result); 12. 13. $result1 = mysqli_query($dbc, $query1); 14. $row1 = mysqli_fetch_assoc($result1); 15. // print ".$row.'/'.$row1." 16. print $row['count(visits.site_id)'].' / '.$row1['count(site_id)']; 17. The divisions also have a check or an unchecked mark to indicate user’s accomplishment. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. $query = "select count(v.site_id), division_name from sites s join visits v on s.site_id = v.site_id where division_name = 'North' and v.user_id = '".$user."' group by division_name" ; $result = mysqli_query($dbc, $query); $row = mysqli_fetch_assoc($result); if ($row['count(v.site_id)'] == '49') { echo "☑";} else { echo "☐"; } Overall look. Rewards Check if the user has completed all the sites in a park. If yes, print a button for getting the reward. If no, print a disabled button. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. $query = "select count(v.site_id), park_name from sites s join visits v on s.site_id = v.site_id where park_name = 'Black Hill Regional Park' and v.user_id = '".$user."' group by park_name" ; $result = mysqli_query($dbc, $query); $row = mysqli_fetch_assoc($result); if ($row['count(v.site_id)'] == '5') { echo ""; 15. echo "
"; echo "
"; 16. 17. } 18. else 19. { echo ""; 20. echo "
"; echo "
"; 21. } 22. 23. The same logic for division rewards and the final reward. User Sign up contains the following features. Check if all the required fields are filled. Check if the username already exists. Check if the Email already exists. Check if the password contains least 1 number, 1 lower case, 1 capital case and being at least 8 characters long. Check if two passwords match. Check phone number format. Check captcha. Password retrieval Check if the user exists Check if the sent email link for password retrieval is expired – expires in 60 mins. Check if two passwords match. Migration: The website needs to be hosted on a server with an SSL certificate – https is required for geolocation. The host server needs to have an email address to send password retrieval emails. Depending on the URL of the server, the password retravel link needs to be modified as well as the email verification URL. They can be located in forgot.php and verify.php. db_connect.php and Mysqli_connect.php need to be modified for server connection. The front page is named as index.php. Document for sites.

Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.7
Linearized                      : No
Page Count                      : 17
Language                        : en-US
Tagged PDF                      : Yes
XMP Toolkit                     : 3.1-701
Producer                        : Microsoft® Word 2016
Creator                         : SHI TU
Creator Tool                    : Microsoft® Word 2016
Create Date                     : 2018:06:06 21:01:29-04:00
Modify Date                     : 2018:06:06 21:01:29-04:00
Document ID                     : uuid:F6967765-F79D-40C6-B322-07C1F871DA98
Instance ID                     : uuid:F6967765-F79D-40C6-B322-07C1F871DA98
Author                          : SHI TU
EXIF Metadata provided by EXIF.tools

Navigation menu