Loop through specific columns and setting value - loops

I have a script but it works pretty slow and Im trying to see if I could make it work faster by possibly making it loop through the columns 10,12,15,17,20,22,25,27,30,32,35,37,40,42,45,47,50,52,55,57 instead of writing an if statement for each column. The way I currently have it works but it's slow and looks like this
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Student Data-NEA" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() == 10 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
if( r.getColumn() == 12 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
if( r.getColumn() == 15 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
if( r.getColumn() == 17 && r.getValue() == 'P') { //checks the column
var nextCell = r.offset(0, 1);
//if( nextCell.getValue() !== '' ) //is empty?
nextCell.setValue("P- N/A");
}
Etc.
What it does is it looks at a column and if there is a P then it offsets 1 column and pastes a P- N/A. Could someone help making the script shorter so it can run faster? Thank you.

You need to use getValues(range). This way you get an array. You can process this array and then use setValues(range) to fill all cells in the range at once with values of the array. It will work much faster.
Probably something like this:
function main() {
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() != "Student Data-NEA") return;
var r = s.getActiveCell(); // current cell
var row = r.getRow(); // index of current row
var row_range = s.getRange("A"+row+":Z"+row); // get range of the row
var row_values = row_range.getValues().flat(); // get array [cell, cell, cell]
var value = "P- N/A";
// change the array (not the sheet)
if (row_values[9] == "P") row_values[10] = value;
if (row_values[11] == "P") row_values[12] = value;
if (row_values[14] == "P") row_values[15] = value;
if (row_values[16] == "P") row_values[17] = value;
// change the sheet
row_range.setValues([row_values]); // set all values for the row at once
}
If your conditions all the same, you can loop through list of columns this way:
var condition = "P";
var columns = [9, 11, 14, 16];
for (var col of columns) {
if (row_values[col] == condition) row_values[col+1] = value;
}
// instead of this
// if (row_values[9] == "P") row_values[10] = value;
// if (row_values[11] == "P") row_values[12] = value;
// if (row_values[14] == "P") row_values[15] = value;
// if (row_values[16] == "P") row_values[17] = value;
Update
I don't know why I do it, since the author of the question still provided almost no information about what he does with the table and we have no sample of the table, etc. But whatever:
If you need to change next cell to "P- N/A" (do you need it? I still have no idea) in some columns if edited cell contains "P", here is a script:
function onEdit(e) {
var s = e.source.getActiveSheet();
if (s.getName() != "Student Data-NEA") return;
var col = e.range.columnStart;
var row = e.range.rowStart;
var range = s.getRange(row,col,1,2);
var range_array = range.getValues();
var cell_value = range_array[0][0];
var next_cell_value = "P- N/A";
var cols = [10, 12, 15, 17];
if (cell_value == "P" && cols.includes(col)) {
range_array[0][1] = next_cell_value;
range.setValues(range_array);
}
}
But actually it can be done much easier and faster with standard Excel-like function (example for the cell "K1"):
=IF(EQ(J1,"P"),"P- N/A","")
Just populate with this function the columns K, M, P, R...

Related

Why array comparison isn't working? (GAS)

The code below used to work. Now, when comparing two arrays, even though there is a difference, as highlighted below, the code says that there is a duplicate.
I've tried it using .join() as well, but I keep getting the same result.
Script:
function SaveEditedEntry() {
const lock = LockService.getScriptLock();
lock.tryLock(3000);
if (lock.hasLock()) {
var sourceSheet = 'Entries';
var destinationSheet = 'Database';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sourceSheet);
var LastRowSource = sheet.getLastRow();
//var LastColumnSource = sheet.getLastColumn();
var entryValues = sheet.getRange(7, 1, LastRowSource, 16).getValues();
var dbSheet = ss.getSheetByName(destinationSheet);
var entryDataPushed = [];
var dbData = dbSheet.getRange(2, 1, dbSheet.getLastRow(), 16).getValues();
var dbDataPushed = [];
//var dbDataPushed = new Array();
var company = sheet.getRange("B3").getValue();
var period = sheet.getRange("B4").getValue();
var entryID = sheet.getRange("J5").getValue();
var timeStamp = new Date();
var user = Session.getActiveUser().getEmail();
if (company == '') {
Browser.msgBox('Make sure that you have chosen a valid company.');
return;
}
if (period == '') {
Browser.msgBox('Please, make sure that you have chosen a valid period.');
return;
}
var emptyRow = 0;
for (var i = 0; i < entryValues.length; i++) {
if (entryValues[i][0] != '') {
emptyRow = i + 1;
}
if (emptyRow < 1) {
Browser.msgBox('Please, make sure that you have entered a transaction.');
return;
}
if (entryValues[i][0] != '') {
entryDataPushed.push(entryValues[i]);
}
}
for (var n = 0; n < dbData.length; n++) {
if (dbData[n][1] != '' && dbData[n][0] == company && dbData[n][14] == period) {
dbDataPushed.push(dbData[n]);
}
}
var duplicate = false;
loop1:
for (var x = 0; x < entryValues.length; x++) {
loop2:
for (var j = 0; j < dbDataPushed.length; j++) {
if (JSON.stringify(entryValues[x]) == JSON.stringify(dbDataPushed[j])) {
duplicate = true;
break loop1;
}
}
}
Logger.log("EntryDataPushed: " + entryDataPushed);
Logger.log("dbDataPushed: " + dbDataPushed);
if (duplicate == true) {
Browser.msgBox('No change has been made.');
return;
This is the logs print:
Could anyone point me to the right direction on getting this solved?
Thank you!
Antonio
You were comparing entryValues vs dbDataPushed but is logging entryDataPushed and dbDataPushed. Is this expected?
Anyways, since you are logging the variables, I assume the variables logged are the ones you need to compare.
Convert them into JSON string by wrapping the variables with JSON.stringify(). I use this all the time when I encounter an issue similar to yours right now.
var duplicate = false;
if (JSON.stringify(entryDataPushed) == JSON.stringify(dbDataPushed)) {
duplicate = true;
}
Output:
See resource below for other ways to properly compare arrays if the above code doesn't work.
Resources:
JSON.stringify()
StackOverflow Reference

How to assign value to Numbers in Array?

Hey everyone so I have an Array private var frames:Array; which I give value and initiate in my constructor function like so frames = [2, 3, 4, 5, 6, 7, 8];
Now I am trying to give a string value to each number in the array for my hitTest Function. I was thinking something on the lines of a for loop and giving them values there but having some issues here is what I have so far:
for (var i:int = 0; i < frames.length; i++)
{
var currentFrameNumber = frames[i];
//assign values to numbers in array
if (currentFrameNumber == 2)
{
trace("2_RED");
currentWires.sRed = "RED";
}
if (currentFrameNumber == 3)
{
trace("GREEN");
currentWires.sGreen = "GREEN";
}
if (currentFrameNumber == 4)
{
trace("BLUE");
currentWires.sBlue = "BLUE";
}
if (currentFrameNumber == 5)
{
trace("YELLOW");
currentWires.sYellow = "YELLOW";
}
if (currentFrameNumber == 6)
{
trace("WHITE");
currentWires.sWhite = "WHITE";
}
if (currentFrameNumber == 7)
{
trace("PURPLE");
currentWires.sPurple = "PURPLE";
}
if (currentFrameNumber == 8)
{
trace("BLACK");
currentWires.sBlack = "BLACK";
}
}
this doesn't work at all. I know I Am missing something crucial. Please any help would be appreciated thanks!
****************UPDATE****************
I have my array of Movie clips like so aClockArray = [playScreen.wire_5, playScreen.wire_6, playScreen.wire_7, playScreen.wire_8];
in my last post I finally figure out how to randomize the array with no repeat like so:
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1);
//nWire = randomNumber(2, 8);
currentWires.gotoAndStop(randomFrame);
}
and above in my frames for loop is where I assign the values to the numbers in the frames array for my hitTest which I try to accomplish like so:
private function wireHitTestFunction():void
{
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
if (redCopper.hitTestObject(currentWires) && currentWires.sRed == "RED")
{
//trace("HIT_ RED");
hasRedWire = false;
redCopper.removeEventListener(MouseEvent.MOUSE_DOWN, redWireFunction);
redWire.removeEventListener(MouseEvent.MOUSE_UP, redWireFunction);
trace("HIT");
}
if (blueCopper.hitTestObject(currentWires) && currentWires.sBlue == "BLUE")
{
//trace("HIT_BLUE");
hasBlueWire = false;
blueCopper.removeEventListener(MouseEvent.MOUSE_DOWN, blueWireFunction);
blueWire.removeEventListener(MouseEvent.MOUSE_UP, blueWireFunction);
trace("HIT");
}
I cant seem to figure this out lost in code haha. I probably have it set up really badly.
basically the game is I have 7 colored wires on the stage that the user can drag and place inside the correct color slot. It was working fine until I had added the var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1); I had to change things around. It was working fine when my original code was like so:
//Loop through wires and make them randomn generate color
for (var i:int = 0; i < aClockArray.length; i++)
{
var currentWires = aClockArray[i];
//var randomFrame:uint = frames.splice(Math.floor(Math.random() * frames.length), 1);
nWire = randomNumber(2, 8);
currentWires.gotoAndStop(nWire);
//If any of the Wires lands on 2,3,etc.. Assign Color for Hit Test
if (nWire == 2)
{
trace("2_RED");
currentWires.sRed = "RED";
}
if (nWire == 3)
{
trace("GREEN");
currentWires.sGreen = "GREEN";
}
if (nWire == 4)
{
trace("BLUE");
currentWires.sBlue = "BLUE";
}
if (nWire == 5)
{
trace("YELLOW");
currentWires.sYellow = "YELLOW";
}
if (nWire == 6)
{
trace("WHITE");
currentWires.sWhite = "WHITE";
}
if (nWire == 7)
{
trace("PURPLE");
currentWires.sPurple = "PURPLE";
}
if (nWire == 8)
{
trace("BLACK");
currentWires.sBlack = "BLACK";
}
}
I'm not sure exactly what issue you're seeing, and it's hard to know exactly what's going on without seeing the entire code, but I'll take a stab at it...
rather than currentWire.sRed = "RED";
use a single variable to represent the current color, like so:
currentWire.color = "RED";
then..
if (redCopper.hitTestObject(currentWires) && currentWires.color== "RED")
{
//trace("HIT_ RED");
hasRedWire = false;
redCopper.removeEventListener(MouseEvent.MOUSE_DOWN, redWireFunction);
redWire.removeEventListener(MouseEvent.MOUSE_UP, redWireFunction);
trace("HIT");
}
if (blueCopper.hitTestObject(currentWires) && currentWires.color== "BLUE")
{
//trace("HIT_BLUE");
hasBlueWire = false;
blueCopper.removeEventListener(MouseEvent.MOUSE_DOWN, blueWireFunction);
blueWire.removeEventListener(MouseEvent.MOUSE_UP, blueWireFunction);
trace("HIT");
}

Actionscript 3 - How to Check if an Array Position Already Exists

Hello my question is as stated. I have a randomly generated dungeon with a player and random blocks. All the rooms in the dungeon are saved in the ROOMS 2D array which contains the data for the rooms. You have a current Row and current Col which is where the player is at. What i need to know is how to say IF there is no room above the current position then change the outside wall graphic to close the exits/doors where there is no room. I have this somewhat working but everyway i change it there is always one room which just will not work if i try to add the code. What i have now is abunch of if statements saying IF ROOMS[currentRow + 1][currentCol](< that would be equal to down) so if one row up exists then change the graphic by doing gotoAndStop. So how or which is the best way to determine if a position exists because with this, it will randomly comeback with errors like "term is undefined and has no properties." Also i have really dirty code, sorry im new, ill try to clean it up later but if any of you feel like it, i wont stop you haha!
Im grateful for any replies! Here is my room class
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Room extends MovieClip{
var room1:Array = new Array();
var room2:Array = new Array();
var room3:Array = new Array();
var room4:Array = new Array();
var room5:Array = new Array();
var room6:Array = new Array();
var room7:Array = new Array();
var room8:Array = new Array();
var room9:Array = new Array();
var room10:Array = new Array();
var currentRow:int = 0;
var currentCol:int = 0;
var box:Box;
var boxes:Array;
var ROOMS:Array;
var onTop:Boolean;
var moved:Boolean;
private var player:Player;
private var walls:Walls;
private var blocker1:Blocker;
private var blocker2:Blocker;
private var blocker3:Blocker;
private var blocker4:Blocker;
private var arrowImage:ArrowSymbol;
public function Room(){
init();
createRooms();//add the walls + boxes of first room to the first array value // later make floors array that contains all the rooms and room array that contains all the boxes and enemies + events
stage.addChild(ROOMS[currentRow][currentCol]);
Constants.wallsRef = ROOMS[currentRow][currentCol];
addEventListener(Event.ENTER_FRAME, update);
stage.addChild(arrowCount);
stage.addChild(arrowImage);
}
function init(){
Constants.stageRef=stage;
player = new Player();
//add walls
walls = new Walls();
Constants.wallsRef=walls;
blocker1 = new Blocker();//BLOCKER WHEN PLAYER TOUCHES IT CHANGES ROOM
blocker1.x = 350;
blocker1.y = 1;
stage.addChild(blocker1);
blocker2 = new Blocker();
blocker2.x = 350;
blocker2.y = 619;
stage.addChild(blocker2);
blocker3 = new Blocker();
blocker3.x = -30;
blocker3.y = 300;
blocker3.rotation = 90;
stage.addChild(blocker3);
blocker4 = new Blocker();
blocker4.x = 700;
blocker4.y = 300;
blocker4.rotation = 90;
stage.addChild(blocker4);
Constants.blockerRef1 = blocker1;
Constants.blockerRef2 = blocker2;
Constants.blockerRef3 = blocker3;
Constants.blockerRef4 = blocker4;
//add player
player.x = 300;
player.y = 200;
stage.addChild(player);
arrowImage = new ArrowSymbol();
arrowImage.x = 630;
arrowImage.y = 30;
box = new Box();
boxes = new Array();
ROOMS = new Array([room2],
[room6, room1, room5], /// THIS IS THE MAP OF THE FLOOR /// GOING UP ON THE GAME IS GOING DOWN ON IT
[room7, room8],
[room3, room9],
[room4]);//THIS WILL EVENTUALLY BE COMPLETELY RANDOMIZED//
onTop = false;
moved = false;
}
function update(e:Event){
arrowCount.text = " " + Constants.arrowNumRef;//arrow amount left
closeUnnecessaryExits();
//UP
if(Constants.blockerRef1.hitTestPoint(player.x,player.y) && moved != true){
stage.removeChild(ROOMS[currentRow][currentCol]);//remove the room you are in so the new room doesnt overlap
currentRow++;//change where the player is in
stage.addChild(ROOMS[currentRow][currentCol]);//add new room
Constants.wallsRef = ROOMS[currentRow][currentCol];//add colision
player.y = 600;
stage.addChild(arrowCount);
stage.addChild(arrowImage);
trace();
moved = true;
}else if(Constants.playerRef.hitTestObject(Constants.blockerRef1) == false && moved == true){
moved = false;
}
//DOWN
if(Constants.blockerRef2.hitTestPoint(player.x,player.y) && moved != true){
//this will be where i want to change rooms
stage.removeChild(ROOMS[currentRow][currentCol]);
currentRow--;
Constants.wallsRef = ROOMS[currentRow][currentCol];
stage.addChild(ROOMS[currentRow][currentCol]);
player.y = 10;//change to 600
moved = true;
trace("changed rooms");
stage.addChild(arrowCount);
stage.addChild(arrowImage);
}else if(Constants.playerRef.hitTestObject(Constants.blockerRef1) == false && moved == true){
moved = false;
}
//LEFT
if(Constants.blockerRef3.hitTestPoint(player.x,player.y) && moved != true){
stage.removeChild(ROOMS[currentRow][currentCol]);//remove the room you are in so the new room doesnt overlap
currentCol--;//change where the player is in
stage.addChild(ROOMS[currentRow][currentCol]);//add new room
Constants.wallsRef = ROOMS[currentRow][currentCol];//add colision
player.x = 600;
stage.addChild(arrowCount);
stage.addChild(arrowImage);
moved = true;
}else if(Constants.playerRef.hitTestObject(Constants.blockerRef1) == false && moved == true){
moved = false;
}
//RIGHT
if(Constants.blockerRef4.hitTestPoint(player.x,player.y) && moved != true){
//this will be where i want to change rooms
stage.removeChild(ROOMS[currentRow][currentCol]);
currentCol++;
Constants.wallsRef = ROOMS[currentRow][currentCol];
stage.addChild(ROOMS[currentRow][currentCol]);
player.x = 10;//change to 600
moved = true;
trace("changed rooms");
stage.addChild(arrowCount);
stage.addChild(arrowImage);
}else if(Constants.playerRef.hitTestObject(Constants.blockerRef1) == false && moved == true){
moved = false;
}
}
function createRooms(){
for(var r = 0; r <ROOMS.length; r++){
walls = new Walls();
addRandomBlocks();
for(var c = 0; c < ROOMS[r].length; c++){
walls = new Walls();
addRandomBlocks();
ROOMS[r][c] = walls;
}
trace(ROOMS[r][c]);
}
}
// [room2, NaN],
// [room6, room1, room5], /// THIS IS THE MAP OF THE FLOOR /// GOING UP ON THE GAME IS GOING DOWN ON IT
// [room7, room8],
// [room3, room9],
// [room4]);
function closeUnnecessaryExits(){
trace("ROW: " + currentRow + " COL: " + currentCol);
var up = ROOMS[currentRow + 1];
var down = ROOMS[currentRow - 1];
var right = ROOMS[currentRow][currentCol + 1];
var left = ROOMS[currentRow][currentCol - 1];
//check to see which outside wasall to use
if(ROOMS[currentRow + 1] == null && up && right && left){
ROOMS[currentRow][currentCol].gotoAndStop(2);
}else if(down == null && left == null && right && up){
ROOMS[currentRow][currentCol].gotoAndStop(3);
}else if(down == null && left == null && up == null && right){
ROOMS[currentRow][currentCol].gotoAndStop(4);
}else if(left == null && down && right && up){// IF HAVING PROBLEMS THEN MAKE THIS MAKE SURE ALL OTHER SIDES ARE TRUE
ROOMS[currentRow][currentCol].gotoAndStop(5);
}else if(down == null && left == null && right == null && up){
ROOMS[currentRow][currentCol].gotoAndStop(6);
}else if(down && up == null && right == null && left == null){
ROOMS[currentRow][currentCol].gotoAndStop(7);
}else if(ROOMS[currentRow + 1][currentCol] == null && ROOMS[currentRow - 1][currentCol] && left && right){
ROOMS[currentRow][currentCol].gotoAndStop(8);
trace("works 1");
}else if(left && right && ROOMS[currentRow - 1][currentCol] == null && ROOMS[currentRow + 1][currentCol] == null){
ROOMS[currentRow][currentCol].gotoAndStop(9);
trace("works 2");
}else if(left && ROOMS[currentRow - 1][currentCol] && right == null && ROOMS[currentRow + 1][currentCol] == null){
ROOMS[currentRow][currentCol].gotoAndStop(10);// LEFT DOWN
trace("works 3");
}else if(left && ROOMS[currentRow + 1][currentCol] && ROOMS[currentRow - 1][currentCol] == null && right == null){
ROOMS[currentRow][currentCol].gotoAndStop(11);//BROKEN left up
trace("working 4");
}else if(left && ROOMS[currentRow + 1][currentCol] == null && ROOMS[currentRow - 1][currentCol] == null && right == null){
ROOMS[currentRow][currentCol].gotoAndStop(12);
trace("works 5");
}else if(right == null && left && up && down){
ROOMS[currentRow][currentCol].gotoAndStop(13);
trace("works 6");
}
}
function addRandomBlocks(){
for(var e=0; e <Math.random() * 10; e++){
//trace("started block");
box = new Box();
box.x = Math.random() * (615 - 100) + 100;
box.y = Math.random() * (500 - 120) + 120;
//colision for block to block
for(var col = 0; col < boxes.length; col++){
if(box.hitTestObject(boxes[col])){
onTop = false;/// THIS NEEDS TO BE TRUE FOR THE DETECTION TO WORK
//trace("THIS BOX IS ON TOP OF ANOTHER");
}
}
if(onTop == false){
boxes.push(box);
walls.addChild(box);
trace("BOX CREATED " + onTop);
//trace(boxes);
}
}
}
}
}
You could streamline your code by creating some simple functions that deal with assigning and accessing values in your 2D array. One that checks if an element within a 2D array exists might look like:
function cellExists(array:Array, x:int, y:int):Boolean {
return array[y] !== undefined && array[y][x] !== undefined;
}
Used like, in your example:
if (cellExists(ROOMS, currentCol, currentRow)) {
//
}
Although with this type of task you would benefit greatly from implementing a class that handles grid + cell data, something along the lines of this to get you started:
public class Grid {
private var _content:Vector.<Vector.<Cell>>;
public function Grid(columns:int, rows:int) {
// Fill _content with empty slots based on columns, rows.
}
public function getCell(x:int, y:int):Cell {}
public function cellExists(x:int, y:int):Boolean {}
}

Validating table rows in a LiveCycle form

I am developing a LiveCycle form that has a table on it that can have a variable amount of rows. I want to only validate it if there is data in one of the columns but not all of them. So I would skip the validation if the row is blank or all the columns in that row are filled in.
Any ideas how to do this. How would I loop through the rows of a table.
Thanks in advance,
Paul
I would tweat your answer a little bit by replacing resolveNodes that is quite slow.
In order to get row count you can use instanceManager TrainerForm._TrainerTable.count
To get a specific item from row list use <RowName>.all.item(index). Be carefull while using this construct because it requires a least one row. Row is a shourtcat for Row[0].
Here is your code with with my upgrades:
var rowCount = TrainerForm.TrainerTable._TrainerData.count;
for (var i=0;i<rowCount;i++)
{
if (TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerName.rawValue == null &&
TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerPrepHrs.rawValue == null &&
TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerArea.selectedIndex == -1 &&
TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerActivity.rawValue == null )
;//check the case where all rows are blank which is valid
else
{
if (TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerName.rawValue == null)
{
TrainerTableValid = false;
TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerName.ui.#textEdit.border.fill.color").value = "255,0,0";
}
if (TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerPrepHrs.rawValue == null)
{
TrainerTableValid = false;
TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerPrepHrs.ui.#numericEdit.border.fill.color").value = "255,0,0";
}
if (TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerArea.selectedIndex == -1)
{
TrainerTableValid = false;
TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerArea.ui.#choiceList.border.fill.color").value = "255,0,0";
}
if (TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerActivity.rawValue == null)
{
TrainerTableValid = false;
TrainerForm.TrainerTable.TrainerData.all.item(i).TrainerActivity.ui.#textEdit.border.fill.color").value = "255,0,0";
}
}
}
You can put your script in validate event of your cells or whole row. The result of validation script is determined by the last line result (true or false); To make validations failure visible you can set form level validation (File->Form Properties->Form Validation->Color Failed Fields).
Another approach (that I personally prefer) is setting field as required using code fieldName.manadatory = "error" when some conditions are met. In order to make field optional just put fieldName.manadatory = "disabled".
Here is what I ended up doing. First I made all fields optional. Then I execute this code from a click event of a button.
var fields = xfa.resolveNodes("TrainerForm.TrainerTable.TrainerData[*]");
for (var i=0;i<fields.length;i++)
{
if (TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerName.rawValue == null &&
TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerPrepHrs.rawValue == null &&
TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerArea.selectedIndex == -1 &&
TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerActivity.rawValue == null )
;//check the case where all rows are blank which is valid
else
{
if (TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerName.rawValue == null)
{
TrainerTableValid = false;
xfa.resolveNode("TrainerForm.TrainerTable.TrainerData[" + i + "].TrainerName.ui.#textEdit.border.fill.color").value = "255,0,0";
}
if (TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerPrepHrs.rawValue == null)
{
TrainerTableValid = false;
xfa.resolveNode("TrainerForm.TrainerTable.TrainerData[" + i + "].TrainerPrepHrs.ui.#numericEdit.border.fill.color").value = "255,0,0";
}
if (TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerArea.selectedIndex == -1)
{
TrainerTableValid = false;
xfa.resolveNode("TrainerForm.TrainerTable.TrainerData[" + i + "].TrainerArea.ui.#choiceList.border.fill.color").value = "255,0,0";
}
if (TrainerForm.TrainerTable.resolveNode("TrainerData[" + i + "]").TrainerActivity.rawValue == null)
{
TrainerTableValid = false;
xfa.resolveNode("TrainerForm.TrainerTable.TrainerData[" + i + "].TrainerActivity.ui.#textEdit.border.fill.color").value = "255,0,0";
}
}
}

AS3 - Remove spaces from an array for word game

I'm building a word search game using the following AS3 code. My problem is I need to have spaces in my array of words, so that I can have things like states names, but I need the spaces removed before the words go into the puzzle.
The other concern is also that when a person selects a word from the puzzle will it still match the word in the list even though the word in the list still has a space.
I've struggled with this for a few days now and could use some help.
I've pasted all appropriate code below, I believe. Thanks.
Rich
// words and grid
private var wordList:Array;
private var usedWords:Array;
private var grid:Array;
// sprites
private var letterSprites:Sprite;
private var wordsSprite:Sprite;
wordList = ("New York,New Jersey,South Carolina,North Carolina").split(",");
// set up the sprites
gameSprite = new Sprite();
addChild(gameSprite);
letterSprites = new Sprite();
gameSprite.addChild(letterSprites);
wordsSprite = new Sprite();
gameSprite.addChild(wordsSprite);
// array of letters
var letters:Array = placeLetters();
// create word list fields and sprites
for(var i:int=0;i<usedWords.length;i++) {
var newWord:TextField = new TextField();
newWord.defaultTextFormat = letterFormatForList;
if(i < 20){ // first list
newWord.x = listXposition;
newWord.y = i*spacingForList+listYposition;
} else { // second list
newWord.x = listXposition + 130;
newWord.y = i*spacingForList+listYposition - (20 * 19);
}
newWord.width = 135;
newWord.height = spacingForList;
newWord.text = usedWords[i];
newWord.selectable = false;
wordsSprite.addChild(newWord);
}
// set game state
dragMode = "none";
numFound = 0;
}
// place the words in a grid of letters
public function placeLetters():Array {
// create empty grid
var letters:Array = new Array();
for(var x:int=0;x<puzzleSize;x++) {
letters[x] = new Array();
for(var y:int=0;y<puzzleSize;y++) {
letters[x][y] = "*";
}
}
// make copy of word list
var wordListCopy:Array = wordList.concat();
usedWords = new Array();
// make 1000 attempts to add words
var repeatTimes:int = 1000;
repeatLoop:while (wordListCopy.length > wordsLeft) {
if (repeatTimes-- <= 0) break;
// pick a random word, location and direction
var wordNum:int = Math.floor(Math.random()*wordListCopy.length);
var word:String = wordListCopy[wordNum].toUpperCase();
x = Math.floor(Math.random()*puzzleSize);
y = Math.floor(Math.random()*puzzleSize);
var dx:int = Math.floor(Math.random()*3)-1;
var dy:int = Math.floor(Math.random()*3)-1;
if ((dx == 0) && (dy == 0)) continue repeatLoop;
// check each spot in grid to see if word fits
letterLoop:for (var j:int=0;j<word.length;j++) {
if ((x+dx*j < 0) || (y+dy*j < 0) || (x+dx*j >= puzzleSize) || (y+dy*j >= puzzleSize)) continue repeatLoop;
var thisLetter:String = letters[x+dx*j][y+dy*j];
if ((thisLetter != "*") && (thisLetter != word.charAt(j))) continue repeatLoop;
}
// insert word into grid
insertLoop:for (j=0;j<word.length;j++) {
letters[x+dx*j][y+dy*j] = word.charAt(j);
}
// remove word from list
wordListCopy.splice(wordNum,1);
usedWords.push(word);
}
// fill rest of grid with random letters
for(x=0;x<puzzleSize;x++) {
for(y=0;y<puzzleSize;y++) {
if (letters[x][y] == "*") {
letters[x][y] = String.fromCharCode(65+Math.floor(Math.random()*26));
}
}
}
return letters;
}
// player clicks down on a letter to start
public function clickLetter(event:MouseEvent) {
var letter:String = event.currentTarget.getChildAt(0).text;
startPoint = findGridPoint(event.currentTarget);
dragMode = "drag";
}
// player dragging over letters
public function overLetter(event:MouseEvent) {
if (dragMode == "drag") {
endPoint = findGridPoint(event.currentTarget);
// if valid range, show outline
outlineSprite.graphics.clear();
if (isValidRange(startPoint,endPoint)) {
drawOutline(outlineSprite,startPoint,endPoint,0xCCCCCC);
}
}
}
// mouse released
public function mouseRelease(event:MouseEvent) {
if (dragMode == "drag") {
dragMode = "none";
outlineSprite.graphics.clear();
// get word and check it
if (isValidRange(startPoint,endPoint)) {
var word = getSelectedWord();
checkWord(word);
}
}
}
// when a letter is clicked, find and return the x and y location
public function findGridPoint(letterSprite:Object):Point {
// loop through all sprites and find this one
for(var x:int=0;x<puzzleSize;x++) {
for(var y:int=0;y<puzzleSize;y++) {
if (grid[x][y] == letterSprite) {
return new Point(x,y);
}
}
}
return null;
}
// determine if range is in the same row, column, or a 45 degree diagonal
public function isValidRange(p1,p2:Point):Boolean {
if (p1.x == p2.x) return true;
if (p1.y == p2.y) return true;
if (Math.abs(p2.x-p1.x) == Math.abs(p2.y-p1.y)) return true;
return false;
}
// draw a thick line from one location to another
public function drawOutline(s:Sprite,p1,p2:Point,c:Number) {
var off:Point = new Point(offset.x+spacing/2, offset.y+spacing/2);
s.graphics.lineStyle(outlineSize,c);
s.graphics.moveTo(p1.x*spacing+off.x ,p1.y*spacing+off.y-3);
s.graphics.lineTo(p2.x*spacing+off.x ,p2.y*spacing+off.y-3);
}
// find selected letters based on start and end points
public function getSelectedWord():String {
// determine dx and dy of selection, and word length
var dx = endPoint.x-startPoint.x;
var dy = endPoint.y-startPoint.y;
var wordLength:Number = Math.max(Math.abs(dx),Math.abs(dy))+1;
// get each character of selection
var word:String = "";
for(var i:int=0;i<wordLength;i++) {
var x = startPoint.x;
if (dx < 0) x -= i;
if (dx > 0) x += i;
var y = startPoint.y;
if (dy < 0) y -= i;
if (dy > 0) y += i;
word += grid[x][y].getChildAt(0).text;
}
return word;
}
// check word against word list
public function checkWord(word:String) {
// loop through words
for(var i:int=0;i<usedWords.length;i++) {
// compare word
if (word == usedWords[i].toUpperCase()) {
foundWord(word);
}
// compare word reversed
var reverseWord:String = word.split("").reverse().join("");
if (reverseWord == usedWords[i].toUpperCase()) {
foundWord(reverseWord);
}
}
}
// word found, remove from list, make outline permanent
public function foundWord(word:String) {
sndSuccess=new success_sound();
sndSuccessChannel=sndSuccess.play(200);
so.data.totalWordsFound = so.data.totalWordsFound + 1;
so.flush();
// draw outline in permanent sprite
drawOutline(oldOutlineSprite,startPoint,endPoint,0xDDDDDD);
// find text field and set it to gray
for(var i:int=0;i<wordsSprite.numChildren;i++) {
if (TextField(wordsSprite.getChildAt(i)).text.toUpperCase() == word) {
TextField(wordsSprite.getChildAt(i)).textColor = 0x777777;
}
}
// see if all have been found
numFound++;
if (numFound == usedWords.length) {
if (so.data.difficulty == "Easy") {
so.data.easyWon = so.data.easyWon + 1;
}
if (so.data.difficulty == "Medium") {
so.data.mediumWon = so.data.mediumWon + 1;
}
if (so.data.difficulty == "Hard") {
so.data.hardWon = so.data.hardWon + 1;
}
so.flush();
endGame();
}
}
I'm hesitant to post an answer as I'm not really sure what's going on, but hopefully this info will help:
Keep your words in the arrays with spaces, that's a good idea. When you want to check against the words in your game, just convert both words to the same format using a function. eg:
var wordList:Array = ("New York,New Jersey,South Carolina,North Carolina").split(",");
var selectedWord:String = "NEWYORK";
// minWord converts all words to the same format of no spaces and all lower case.
function minWord(word:String):String {
return word.replace(/\s/g, "").toLowerCase();
}
// this loop checks all the words from your array against the selectedWord.
for each(var word:String in wordList) {
trace(minWord(word) + " == " + minWord(selectedWord) + "; ", minWord(word) == minWord(selectedWord));
}
Hope that helps!

Resources