I need to create a "Dice" object using javascript. I have the start but am running into some fundamental errors.
var Die = function (){
this.sides = 6;
}
var Die = function (value){
this.sides = value;
}
Die.prototype.roll = function(){
var result = Math.floor((Math.random()*sides)+1);
return;
}
Die.prototype.getValue = function(){
return sides;
}
I want to have a default six sided die but if the user wants to add a different number of sides they should have that option, hence the attempt at an overloaded constructor. the roll method is supposed to simulate "rolling".
I don't really know where I am going wrong but my methods are not working
Thank You!
Your first two statements are overriding each other, you should combine them into one, as follows.
var Die = function(sides) {
this.sides = sides || 6;
}
The only error in your roll and getValue methods is that to access the sides variable you must use this.sides, as it is a property of the Die object. The two functions can also be combined into one quite easily.
Die.prototype.roll = function() {
return Math.floor((Math.random()*this.sides)+1);
}
Example usage:
var die = new Die();
console.log(die.roll()); // --> 4
var five_sided_die = new Die(5);
console.log(five_sided_die.roll()); // --> 3
Related
I am building a simple array of jsonobjects via:
var jsonObjArr = sessionScope.get("tmpAssessors");
var jsonObj:com.ibm.commons.util.io.json.JsonJavaObject = new com.ibm.commons.util.io.json.JsonJavaObject();
var area = getComponent("inpArea").value;
var person = getComponent("personField").value;
jsonObj.putJsonProperty("area", area);
jsonObj.putJsonProperty("person", person);
jsonObjArr.push(jsonObj);
sessionScope.put("tmpAssessors",jsonObjArr);
However I would like to check if a similar jsonobject (same key-pair values) is already in the array so I will not push it in a second time.
How can I check this?
Provided that JsonJavaObject.equals performs a correct equality check, your code should work if you replace jsonObjArr.push(jsonObj); with the following:
var _doesArrayContainElement=function(a,e){
var i;
for (i=0;i<a.length;i++) {
if (a[i].equals(e)) return true;
}
return false;
}
if (!_doesArrayContainElement(jsonObjArr,jsonObj)) jsonObjArr.push(jsonObj);
I am very new to this and hoping it's something that should have been obvious.
When I run the code below, the Array newHole and newArray both return 1 on the trace. Originally the code was built with only the newHole array, but I created the newArray in the hopes of troubleshooting. It did not help. The class for bulletHole contains no extra code so I didn't post that.
Thank you.
import flash.display.*;
import flash.events.*;
import flash.ui.Mouse;
Mouse.hide();
var myReticle:MovieClip;
var holeArray:Array = new Array();
var randomHole:Number = randomNumber(1, 5);
var newHole:bulletHole = new bulletHole();
var newArray:Array = new Array();
stage.addEventListener(MouseEvent.MOUSE_MOVE, followReticle);
stage.addEventListener(MouseEvent.CLICK, myFire);
stage.addEventListener(MouseEvent.CLICK, checkCount);
function followReticle(event:MouseEvent):void
{
myReticle.x = mouseX;
myReticle.y = mouseY;
}
function myFire(int):void
{
stage.addChild(newHole);
newHole.x = myReticle.x;
newHole.y = myReticle.y;
//holeArray.push(newHole);
newHole.gotoAndStop(randomHole);
//trace(holeArray.length);
}
function checkCount(int):void
{
newArray.push("A");
trace(newArray.length);
}
function randomNumber(low:Number=0, high:Number=1):Number
{
return Math.floor(Math.random() * (1+high-low)) + low;
}
Most likely the issue is that the code you've posted is running over and over again. In other words, you have a looping timeline that eventually goes back to the frame that the code you've shown is on.
Whenever that frame is reached, you have the following:
var holeArray:Array = new Array();
Which creates a new array replacing what used to be in that var.
To solve this, you either need to:
take the code out of the timeline (put it in a class file and attach that as the document class of your project)
re-architect your timeline so the first frame is only reached 1 time
put some checks in so that the code only runs the first time the frame is reached.
Here is an example of the latter option:
//just define the array, don't create it
var holeArray:Array;
//if the array is null, create it (it will only be null the first time this code is run
if(!holeArray){
holeArray = new Array();
}
This line is incorrect:
function myFire(int):void {
Because the function is triggered from a mouse event listener it should read:
function myFire(e:MouseEvent):void {
What you are doing is passing a undefined int to the function. Hope this helps.
EDIT: You should delete the clickCount event listener and function as they're not needed.
Also notice that you should move this line to the top of your myFire function or else you will keep replacing this MovieClip instead of creating it again:
var newHole:bulletHole = new bulletHole();
I have this in the translation json file:
{
"test_key" : "Var1: {{var1}} Var2: {{var2}} Var3: {{var3}}"
}
For this to work, I need to provide var1, var2, and var 3. For example:
$translate('test_key', { var1: 1, var2: 2, var3: 3 });
The issue now is that var1, var2, var3 could be any dynamic variables. What I need now is to get all the list of dynamic variables so I can provide whatever values it may need.
Ideally, this is the goal I am trying to achieve (pseudo code)
var dynamicVars = getDynamicVarList(); // I need this, but how?
dynamicVars.forEach(function (key) {
switch (key) {
case "var1":
return 1;
case "var2":
return 2;
case "var3":
return 3;
default:
return null;
}
});
If it is Pascal Precht translate, then you set JSON file in module options, before application init. It's rather not possible with standard mechanisms. It offer JSON, but when it is loaded, then it's hard to change something, without changing source code of angular translate module.
If the reason you want this is to have many languages, then you can set many languages codes in $translate.
Another solution is to load JSON from server, which performs operations on var1, var2, var3 and hence returns static json, but you can do $http calls with commands to change variables in switch statement.
It looks somehow linguistic approach, Java is good for this. Grails may be fine framework for returning REST services.
Again, to restate the problem, the issue is that you do not know ahead of time which dynamic variables are to be used.
I solved the issue by using a customer interpolator.
So when you do
{{'testkey'|translate}}
and your lang.json has:
"testkey" :"this is number {{variable1}}"
It will get resolved to
this is number 1
Code:
app.factory('customTranslateInterpolator',
["$interpolate",
function ($interpolate) {
var $locale;
var customTranslateInterpolator = {};
/**
* This will be your custom dynamic vars resolution method
*/
var resolveExpressions = function (expressions) {
var values = {};
expressions.forEach(function (key) {
values[key] = resolveVariable(key);
});
return values;
}
/**
* The actual method for key:value mapping
*/
var resolveVariable = function(key) {
var retVal;
switch (key) {
case "variable1":
retVal = 1;
break;
default:
retVal = "";
}
return retVal;
}
customTranslateInterpolator.setLocale = function (locale) {
$locale = locale;
}
customTranslateInterpolator.getInterpolationIdentifier = function () {
return 'custom';
},
/**
* Custom interpolate
* interpolateParams will overwrite resolve expressions. This will allow developers
* to pass values to the translate directives or by using $translate service.
*
* #param {string} string the string retrieved from the language json file
* #param {object} interpolateParams the {key:value} object passed to the angular-translate features.
*/
customTranslateInterpolator.interpolate = function (string, interpolateParams) {
var result;
interpolateParams = interpolateParams || {
};
// Retrieve expressions and resolve them
var interpolatedString = $interpolate(string);
var resolvedExpressions = resolveExpressions(interpolatedString.expressions);
// Merge interpolateParams onto resolvedExpressions so that interpolateParams overwrites resolvedExpressions
angular.extend(resolvedExpressions, interpolateParams);
result = interpolatedString(resolvedExpressions);
return result;
}
return customTranslateInterpolator;
}]);
make sure you let angular-translate know you are using a custom interpolator
$translateProvider.useInterpolation('customTranslateInterpolator');
Note that you can still provide your own translate-values, and this will override whatever you have in resolveVariable()
So if you do
{{'testkey' | translate:"{variable1:'2'}"}}
It will resolve to
this is number 2
Hope this helps others.
-Lucky M.
What is the best effective way to collect data from a table using protractor.
I collecting the data shown in the code below and it is taking 20-30 seconds for 10 rows.
The buildStr counter is for creating a object for every row, 8 is the number of columns.
row = {};
gridRows = [];
element.all(by.css('#contenttableGrid div[role="gridcell"] div')).each(function(element){
element.getText().then(function(text){
row[headerName[buildStr]] = text;
buildStr++;
if(buildStr === 8){
buildStr = 0;
gridRows[rowCounter] = row;
rowCounter++;
row = {};
}
});
});
One way to speed it up that I see is to extract all the data right on the page by injecting script on it. It could be done with the help of browser.executeScript() (docs). In your sample Protractor has to make a request to the browser any time you call getText(), nubmer of calls it makes = number of cells in your table. But using browser.executeScript() it will make one call and do all the stuff in the browser, which can be really fast. Then you can simply return this data back to a test spec and use it via Promises.
var headerName = {};
// I assume that this variable holds names for headers
// you can pass data from test spec to injected script as arguments (below)
// promise will be resolved with the value you return from `executeScript`
var promise = browser.executeScript(function (headerName) {
// all the stuff inside this function happens on your page under test
// it is not a Protractor environment
var buildStr = 0;
var rowCounter = 0;
var row = {};
var gridRows = [];
var cells = document.querySelectorAll('#contenttableGrid div[role="gridcell"] div');
for (var i = 0, l = cells.length; i < l; i++) {
var text = cells[i].textContent;
// `headerName` object is passed as an argument from test spec
row[headerName[buildStr]] = text;
buildStr++;
if (buildStr === 8) {
buildStr = 0;
gridRows[rowCounter] = row;
rowCounter++;
row = {};
}
}
// return all collected data back to test spec
return gridRows;
}, headerName); // pass helper object from test spec to injectable function
promise.then(function (gridData) {
console.log(gridData); // result of computations
});
Make sure to read docs for browser.executeScript() if you want to use it, because it has a lot of specific moments.
I'm using ObjectEvents to give ActivityPoints to current user based on fields user filled.
Now for example if user register and fill FirstName I will give 10 points to user.
The problem is that I'm handling ObjectEvents.Update.After and inside it I'm updating userSettings.This causes a unlimited loop and application stops working.
is there any work around?
this is the code block:
var className = e.Object.TypeInfo.ObjectClassName;
DataClassInfo dci = DataClassInfoProvider.GetDataClass(className);
if (dci != null)
{
var fi = new FormInfo(dci.ClassFormDefinition);
if (fi != null)
{
var stopProccess = true;
var fields = new List<FormFieldInfo>();
foreach (var changedColumn in e.Object.ChangedColumns())
{
var field = fi.GetFormField(changedColumn);
var activityPointMacro = ValidationHelper.GetString(field.Settings["ActivityPointMacro"], "");
if (!string.IsNullOrEmpty(activityPointMacro))
{
fields.Add(field);
stopProccess = false;
}
}
if (!stopProccess)
{
var contextResolver = CMSContext.CurrentResolver.CreateContextChild();
foreach (FormCategoryInfo info in fi.ItemsList.OfType<FormCategoryInfo>())
{
contextResolver.SetNamedSourceData(info.CategoryName, info);
}
EditingFormControl data = new EditingFormControl();
foreach (FormFieldInfo info2 in fi.ItemsList.OfType<FormFieldInfo>())
{
contextResolver.SetNamedSourceData(info2.Name, data);
}
foreach (var field in fields)
{
{
var activityPointMacro = ValidationHelper.GetString(field.Settings["ActivityPointMacro"], "");
var activityPoint =
ValidationHelper.GetInteger(contextResolver.ResolveMacros(activityPointMacro), 0);
CMSContext.CurrentUser.UserSettings.UserActivityPoints += activityPoint;
CMSContext.CurrentUser.UserSettings.Update();
}
}
}
}
}
If you just need to give points for user fields then you could just use ObjectEvents.Update.Before, check fields are not empty and assign points. But i can see from the code, you want to have something more complex bulit over macro expressions. So I have a few suggestions for you.
1) ObjectEvents.Update.Before instead of ObjectEvents.Update.After still may be a good idea. Ideally you set your additional values and all is set during one update.
2) Watch only the class names you need
3) Always prefer Provider.SetInfo methods over info.Update(). In case of user settings it's best to set whole user info, so UserInfoProvider.SetUserInfo. Provider methods may add some additional important logic.
4) The code seems like it'll add the points with every update of a user
5) if you are still running into a loop, you need to flag somehow, that some part of code should not be executed again. The best way is to use RequestStockHelper class - add a bool value with a specificname like "PointsProcessed".