Changing database entry given player ID from Javascript - javascript

I am writing a javascript game with three different levels which can be accessed from an html form in the index.html page. I also have a list of players stored in a database and I need to:
Prevent players from accessing levels they have already completed, and
Prevent players from starting a new level until every other player has finished the current level
The way I thought to achieve this was to create two database columns named "level_1" and "level_2" which are set to 0 at the beginning of the level and should change to 1 once the level is complete, like so:
*beginning of game
player_ID level_1 level_2
1 0 0
2 0 0
3 0 0
*level one is completed
player_ID level_1 level_2
1 1 0
2 1 0
3 1 0
*level two is completed
player_ID level_1 level_2
1 1 1
2 1 1
3 1 1
When each entry in column "level_1" is changed to 1 I would disable the level 1 option in the html form and "unlock" the level 2 option. The same applies to the second and third levels.
However, I am unsure how to do this using javascript and php. I have a counter in javascript that records the player moves. When the moves go to zero the level is over and the final score is displayed:
if (moves==0){
document.getElementById('endgame_screen').style.display = "flex";
document.getElementById('score').innerHTML = points
}
I also stored the level and id form choices in the same javascript file:
var level = sessionStorage.getItem('level');
var id = sessionStorage.getItem('id');
What I have been struggling to do is opening the php file from the game javascript file and updating the database entries based on level and id. I know the best way would be to fetch the php file like:
fetch("levels.php", {method="POST"}
but then I get stuck as I am not very familiar with the SQL and PHP syntaxes and I don't know how to send the level and id data through PHP, nor how to update the database. I am also not sure how to then disable the form choices which are on another html page (my guess would be to trigger another PHP file when the form is opened that checks whether there are any zeros in the two database columns and updates the form accordingly).
Any help is appreciated!

You will have to write al least a minimal script in PHP to interact with the database.
The bare minimum would be:
<?php
$con = mysqli_connect("localhost","user","password","dbname");
mysqli_query($con, "UPDATE table SET level=1 WHERE user='johndoe'");
?>
But this is of course the bare minimum, from here you can play with your variables, you can process return values, etc. Also watch our for SQL injection.
You will have to learn a bit of MySQL to do this. Here are a few simple examples that can help:
Retrieve information from the database:
SELECT * FROM table_name;
https://www.w3schools.com/sql/sql_select.asp
Create a new record in the database:
INSERT INTO table_name VALUES (value1, value2, value3, ...);
https://www.w3schools.com/sql/sql_insert.asp
Update a record in the database:
UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;
https://www.w3schools.com/sql/sql_update.asp
Detele a record in the database:
DELETE FROM table_name WHERE condition;
https://www.w3schools.com/sql/sql_delete.asp

Related

Google Apps Script: Type Error Onform Submit

I'm new to google apps script and i have issues with my macro script and require some help / advice. I am using google apps script btw.
TLDR version:
TypeError: Cannot read property '0' of undefined that happens and i was wondering how to resolve and troubleshoot it, also appreciate any feedback or advice that you guys might have.
Detailed version:
I have a google spreadsheet linked 3 different forms called form 2, 3, 4. As per usual, when a form is submitted, the data is populated into the individual-linked sheets. (let's call them sheets 2,3,4 respectively)
Now, the purpose for spreadsheet 3 and 4 is to collate and track movement and submission of customer's orders via the usage of timestamps. For each order, it could contain multiple serial numbers, each serial number representing an unique item in their order.
(For example, Mike's order is order number : ORDER-001, his order contains 3 serial numbers, LPN-001 ,LPN-002 and LPN-003, which in turn represents Milk and Cereal and Coffee)
When ORDER-001 is retrieved from the warehouse, the form 3 is submitted to indicate Mike's order has been taken out of the warehouse and sent to the supermarket.
Now, when he submits his order into Form 3, during the form submission, he might list the items in a single row). When the data is sent to the spreadsheet 3, it comes in the form of a list of serial numbers(LPN) in a single cell. What my script does is on the submission of order to Form 3, there is a trigger, the data submitted to spreadsheet 3 is populated on another spreadsheet called Form 3 - (Individual) , to split the rows properly.
(Actual example can see sheet itself)
Eg. Spreadsheet 3
|Name|Order no.___|________LPN no. _____________|timestamp|
| Mike | ORDER-001 | LPN-001,LPN-002,LPN-003 |29/11/21 10:30|
Eg. Spreadsheet 3-(Individual)
|Name|Order no.|LPN no.|timestamp_|
| Mike |ORDER-001| LPN-001|29/11/21 10:30|
| Mike |ORDER-001| LPN-002|29/11/21 10:30|
| Mike |ORDER-001| LPN-003|29/11/21 10:30|
Form 4 is form is used by the supermarket manager. The manager receives the Order number ORDER-001, and has to go and retrieve the goods to prepare to deliver and outbound to the customer. Before outbounding the good, he has to fill form 4 to indicate that he has went to retrieve the order package. Similar to form 3, during the submission of the form, the LPNs are not in individual rows. There is a trigger set to this and a separate Spreadsheet known as " 4 - Outbounding (LPN Deactivation)" to split into individual rows.
For Spreadsheet "3 - LPN Movement Form" and it's 2nd spreadsheet "3 - LPN Movement (Individual)", it is running smoothly and no data errors.
However the majority of errors happens during form 4. For Spreadsheet 4-(Individual), the TypeError: Cannot read property '0' of undefined appears and I don't know how to resolve it. For the trigger during onformsubmit, the data in spreadsheet 4-2 is sometimes populated and there are always random missing numbers. (eg missing random LPN-002 for Mike's order)
Here' my sample code:
// When a form is submitted, this script gets activated
// It will activate the correct function for the form that is submitted
// There are forms that will not activate the script
function formSubmit(e){
Logger.log(e.range.getSheet().getName());
switch(e.range.getSheet().getName()){
case "3 - LPN Movement Form":
onLPNMovementFormSubmit(e);
break;
case "4 - Outbounding Form":
onGoodsOutboundingFormSubmit(e);
break;
}
}
//data processing functions that support the individual forms
var wms = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1097mFk6BTfopXwZ5fSX3h0YpLzaW2xs7YILwck4-6HA/');
var lpnDeactivationSheet = wms.getSheetByName("4 - Outbounding (LPN Deactivation)");
var lpnMovementSheet = wms.getSheetByName("3 - LPN Movement (Individual)");
function insertRowWithValues(inputSheet , dataArray){
SpreadsheetApp.setActiveSheet(lpnDeactivationSheet);
inputSheet.insertRows(2, 1);//shift all rows down by one from row 2
inputSheet.getRange(2,1,1,dataArray.length)//(start row, start col umn, number of rows, number of columns
.setValues([dataArray]);
}
function splitLines(inputText){
return inputText.split(/\r?\n/);
}
function onLPNMovementFormSubmit(event) {
var form = event.namedValues;
lpnList = splitLines(form['License Plate Number (LPN)'][0]);
for (key in lpnList){
insertRowWithValues(lpnMovementSheet,
[lpnList[key],
form['Origin Location ID'],
form['Destination Location ID'],
form['Email address'],
form['Timestamp']]);
}
}
function onGoodsOutboundingFormSubmit(event) {
var formTwo = event.namedValues;
lpnListTwo = splitLines(formTwo['License Plate Number (LPN)'][0]);
for (key in lpnListTwo){
insertRowWithValues(lpnDeactivationSheet,
[lpnList[key],
formTwo['Outbound Request ID'],
formTwo['PO Number'],
formTwo['Goods Condition'],
formTwo['Goods Condition Remarks'],
formTwo['Email address'],
formTwo['Timestamp']]);
}
}
Any advice / help ?Thanks in advance !!!!!!
Link: https://docs.google.com/spreadsheets/d/1097mFk6BTfopXwZ5fSX3h0YpLzaW2xs7YILwck4-6HA/edit?usp=sharing

How can I INSERT new values and values from an already existing table?

I'm currently learning MySQL and have learned the INSERTO INTO statement and the INSERT INTO SELECT statement.
The INSERT INTO statement works like this:
INSERT INTO table_name (column1, column2, column3, ...) VALUES (value1, value2, value3, ...);
While the INSERT INTO SELECT works like this:
INSERT INTO table2 (column1, column2, column3, ...)
SELECT column1, column2, column3, ...
FROM table1
WHERE condition;
What I'm trying to do is add new values while also adding values that I already have stored in another table.
con.query("INSERT INTO vehicles (vehicleType, vehicleModel, vehicleOwner, vehicleSpawnX, vehicleSpawnY, vehicleSpawnZ)")
From the query above, I already have the vehicleOwner value stored in another table, while the other ones I've just gotten.
How can I do this? Add a VALUES statement before SELECT?
I'm using SQL Workbench 8.0 and JavaScript. Also, all the values are NOT NULL, so I can't make two different queries, unless on the first one I add temporary values that I'll update on the second one.
What I want to replace:
vehicleType -> "players"
vehicleModel -> vehicleCreate.model
vehicleOwner -> playerID FROM players table
vehicleSpawnX -> pos.x
vehicleSpawnY -> pos.y
vehicleSpawnZ -> pos.z
Thanks!
It's not possible... But you can select data and store that on variables, then you will store it in another table
You would construct a query. Your data model is a bit hard to follow since you give no examples of the data or of what you really want to do.
So let me give a simpler example. Say, you have a table with two columns for two players and you want to put the ids into a table -- but using their names. The query would look like:
insert into pairs (playerId1, playerId2)
select p1.playerId, p2.playerId
from players p1 join
players p2
on p1.name = ? and p2.name = ?;
The ? are for parameter placeholders. I assume you know to aways use parameters when passing values into a query.

comparing two tables with mysql

I tried to search for an answer to this but I'm not sure if there are any answers to this question because I'm not quite sure how to word it correctly... Here I have two tables
Recipe ingredient table
Recipe_id|ingredient_id
ifqvv |1
ifqvv |2
User ingredient table
User_id|ingredient_id
1 |1
1 |2
2 |1
3 |3
I need to compare these table to where if both recipe and user ingredients_id are a complete match it will return a 1, or if the ingredients are greater than 0 it'll return a 2, and 3 for no matches. For Example, a query for User 1 will return a 1, User 2 a 2, and User 3 a 3. I'm not sure if this is something I'll have to code but I was told by someone that this is possible with little information, which led me here
Assuming you also have a user table, you could achieve this by cross-joining the user with the recipe_ingredients table and then left-joining the user_ingredients table, e.g.:
SELECT u.user_id, ri.recipe_id,
COUNT(ui.ingredient_id) AS available_ingredients, -- Number of ingredients the user has that are required to cook this recipe
COUNT(ri.ingredient_id) AS required_ingredients, -- Number of ingredients that are required to cook this recipe
CASE
WHEN COUNT(ui.ingredient_id) = COUNT(ri.ingredient_id) THEN 'can_cook'
WHEN COUNT(ui.ingredient_id) > 0 THEN 'has_some_ingredients'
ELSE 'has_no_ingredients'
END AS state
FROM users u
CROSS JOIN recipe_ingredients ri
LEFT JOIN user_ingredients ui ON(ri.ingredient_id = ui.ingredient_id AND u.user_id = ui.user_id)
GROUP BY u.user_id, ri.recipe_id
ORDER BY u.user_id, ri.recipe_id
If you want to limit it to a certain user / recipe, just use a where clause:
WHERE u.user_id = 1 AND ri.recipe_id = 'ifqvv'
You can try it live here: DB Fiddle
If you don't have an users table then you can replace
FROM users u with FROM (SELECT DISTINCT user_id FROM user_ingredients) u
DB Fiddle

AngularJS - Sorting ng-repeat on string with numbers in them

I have a list of objects in a table-view i would like to sort properly.
Amongst other things, my objects contain a name-field. This name field can also contain numbers, so for example:
Chairman
Seat 1
Seat 2
Seat 3
Seat 11
Seat 12
Seat 23
Secretary
This is however sorted like this:
Chairman
Seat 1
Seat 11
Seat 12
Seat 2
Seat 23
Seat 3
Secretary
This doesn't seem like a natural way of sorting my list when sorting by name.
Now i'm using the ng-repeat like this:
seat in seats | orderBy:orderField:orderReverse track by seat.id
Where orderfield is some variable that is set when clicking the table header and orderReverse is too for reversing.
I've tried making a custom filter to makes sure it behaves properly but i failed. It seems that Javascript just won't order it normally unless i break up the string. But i'd rather not because the data is often updated by polling. Another way would be to force leading zero's but since users are entering this stuff manually i'm not sure if i should.
Also, its not only names with numbers in them, so i can't just completely cut them off
So, any suggestions on how to make this list show normally?
Edit: cleared up some info about the problem.
You can use a custom sort function with orderBy (it can take custom sorting function too)
define a sort function in your controller:
$scope.sorter = function (a){
return parseInt(a.replace( /^\D+/g, '')); // gets number from a string
}
and then in your template
seat in seats | orderBy:sorter track by seat.id
Edit as per the modified problem statement:
Do manual sorting in controller instead of with ng-repeart using naturalSort
$scope.seats = [{"id": "Seat 12"},{"id": "Seat 3"},{"id": "Seat 1"},{"id": "Seat 2"},{"id": "Secretary"}];
$scope.seats.sort(function(a,b) {
return naturalSort(a.id, b.id);
})
or check this angular module http://blog.overzealous.com/post/55829457993/natural-sorting-within-angular-js and the fiddle demonstrating it - http://jsfiddle.net/wE7H2/3/

How to delete selected checkbox rows in an Oracle APEX Classic Report using Ajax

Within Oracle APEX v4.2.2, I have a simple classic report that has as a first column, a checkbox f50 setup attached to the table's ID column, which will allow a user to check all or specific rows and remove these records from the report/table.
An example report might be something like:
ID Col2 Col3 Col4
----------------------------
1 10 20 30
2 5 8 9
3 92 88 12
4 1 2 44
5 95 77 88
The requirement I am after is that I want to perform this whole process of checking the IDs and the removal of these records done without having to submit the whole page but would like it done via an AJAX method using apex.process.server if possible.
UPDATE: Just a bit more background on this requirement based on the report I am attempting to hook this apex.process.server checkbox IDs, i.e.:
ID Report Column above within Report Attributes heading looks like this:
<input type="checkbox" label="Select Code" onclick="$f_CheckFirstColumn(this)" />
Drilling down into this ID column under HTML Expression is the following:
<input type="checkbox" #ID# value="#ID#" name="f50" id="f50_#ROWNUM#"/>
Region Source:
SELECT A.ID,
A.REQ_NO COL2,
A.CODE_ID||apex_item.hidden(20, A.CODE_ID)||apex_item.hidden(30, A.ID) COL3,
GROUP_VALUE COL4
FROM MY_TABLE A
WHERE A.REQ_NO = :REQ_NO
I believe inorder to have APEX store the values within the apex_application.g_f50.countarray of the IDs to be removed, the page needs to be submitted.
Using apex.process.server, can the ids, as they are checked, be passed as a JavaScript array to an on demand process that will then use these ids to perform the required delete operation?
How can I achieve the above via an AJAX means (no page refresh at all)?
Given this query for a report
select
"EMPNO",
"ENAME",
apex_item.checkbox2(2, 0) check1,
apex_item.checkbox2(3, 0) check2,
apex_item.checkbox2(4, 0) check3
from EMP
With EMPNO set to "Hidden" - so it'll generate a hidden input item appended to the last column.
To update a certain record you'll need a PK and a value to update the row with. That is why I'm using EMPNO. I'll pass that to the on-demand process.
function selectorToArray(pSelector){
function getVal(pNd){
switch ( pNd.nodeName ) {
case "INPUT":
switch ( pNd.type ) {
case "checkbox":
return $(pNd).prop("checked");
break;
default:
return $(pNd).val();
};
break;
default:
return $(pNd).val()
};
};
var lArray = [];
$(pSelector).each(function(){
lArray.push(getVal(this));
});
return lArray;
};
The function selectorToArray will fetch the values for the given selector to an array and get the value. As you might know, you can pass values to a process with x01, x02, ... But there are also arrays: f01, f02,...
With the following code you can send values over to the ondemand process:
function sendCheckboxes(){
var lf01 = [], lf02 = [], lf03 = [], lf04 = [];
lf01 = selectorToArray("input[name=f01]");
lf02 = selectorToArray("input[name=f02]");
lf03 = selectorToArray("input[name=f03]");
lf04 = selectorToArray("input[name=f04]");
apex.server.process("PROCESS_CHECKBOXES", {f01: lf01, f02: lf02, f03: lf03, f04: lf04});
};
You can use those just like you would otherwise: loop over them:
DECLARE
l_pk VARCHAR2(30);
l_check1 VARCHAR2(30);
l_check2 VARCHAR2(30);
l_check3 VARCHAR2(30);
BEGIN
-- f01: PK
-- f02: checkbox values column1
FOR i IN 1..apex_application.g_f01.count
LOOP
l_pk := apex_application.g_f01(i);
l_check1 := apex_application.g_f02(i);
l_check2 := apex_application.g_f03(i);
l_check3 := apex_application.g_f04(i);
apex_debug.message('Record with PK '||l_pk||': check1? '||NVL(l_check1, 'NO')||': check2? '||NVL(l_check2, 'NO')||': check3? '||NVL(l_check3, 'NO'));
END LOOP;
END;
In your code, there are 3 item arrays: f20, f30 and f50. f30 holds the row PK value, while f50 is used for the checkbox.
Don't be fooled by the array naming. Apex itself uses the f## arrays for submission, true enough. And your items with name f50 will indeed be in array g_f50 on page submit.
You can however also use arrays f01 to f20 (don't think it goes up to 50) for ajax calls! They're a great addition to the variables x01-x20!
When using the arrays to send a bulk of values to your process, instead of one-by-one, I think it's most useful to not just send an array of PK values, with a position-matched array of values to interact with. This isn't as valuable when you use a report without pagination though, but still. With pagination, the idea is that you don't really know what set of data was just interacted with. Of 100 records, 10 rows were presented. Of those 10 rows, 6 were checked on render, and on submit only 5 are. Which ones are checked and which ones are unchecked. Knowing which 5 are checked doesn't mean you know the unchecked ones.
When you include a PK column however, you'll always have those 10 rows and you're able to identify clearly which records has been checked or unchecked.
For instance, 10 records in your report will (=should!) mean that 10 values are put in an array (eg l_f01) with the PK value and 10 more values are put in another array (eg l_f02) with eg a checked indicator. So when passing those on to the on-demand process, you'll be able to loop over array f01 reliably, and fetch the checked or unchecked indicator from array f02 with your current index variable used for f01.
Plainly put, you're building up 2 arrays with this sort of value set:
f01 - IDs | f02 - checkeds
----------|---------------
4520 | false
4521 | true
4527 | false
4561 | true
4578 | true

Categories