Need Help, I have totalA - totalB - totalC - totalD, need to select the highest variable from this 4 but if the highest one equal an other one, must show which variables equals.
I have used this code but when it meets the equals ( A = B = C ) it dispalys just D
var aNumber:Array = new Array(totalA , totalB , totalC , totalD );
for(var i:Number = 0; i < aNumber.length; i++)
{
if(aNumber[i] < aNumber[i+1])
{
bigger = aNumber[i+1];
}
}
If you're wanting to output a letter/etc for the scores, I'd use an object/dictionary rather than a straight array.
Basically, the algorithm would be:
Capture the scores in an object/dictionary, where the key is the name of the player and the value is their score.
Enumerate each item/player in the object/dictionary and compare the current score to the maximum score.
If the current score is greater than the maximum score, clear all previous winners, set the new maximum score and add the current player to the winners.
If the current score is equal to the maximum score, add the current player to the winners array.
Following is some hastily concocted actionscript.
var scores:Object = {
'A': totalA,
'B': totalB,
'C': totalC,
'D': totalD
};
var maxScore:Number = -1;
var winners:Array = new Array();
for(var player:String in scores)
{
var score:Number = scores[player];
if (score > maxScore)
{
maxScore = score;
winners = new Array();
winners.push(player);
}
else if (score == maxScore)
{
winners.push(player);
}
}
At the end of this segment of code, you should have the highest score in maxScore and the names of the winning players in the winners array.
var aNumber:Array = new Array(totalA , totalB , totalC , totalD );
bigger = aNumber[0];
for(var i:Number = 1, var j:Number = (aNumber.length)-1; i<j ; i++)
{
if(bigger < aNumber[i])
{
bigger = aNumber[i];
}
}
var highest:Array = new Array();
highest[] = bigger;
for(var i:Number = 0, var j:Number = (aNumber.length); i<j ; i++){
if(aNumber[i] == bigger){
highest[] = aNumber[i];
}
}
Array highest will now hold the highest score(s)
This solution can be a bit more elegant (assuming that a array contains integer values):
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.collections.Sort;
import mx.collections.SortField;
import mx.controls.Alert;
private var array:Array = [1,2,3,4,3];
public function init():void{
var maxValue:Number = getMaxValue(new ArrayCollection(array));
Alert.show(String(maxValue)); //show value 4
}
private function getMaxValue(tempArr:ArrayCollection):Number {
var dataSort:Sort = new Sort();
dataSort.fields = [new SortField(null,false,true,true)];;
tempArr.sort = dataSort;
tempArr.refresh();
return tempArr[0];
}
]]>
</mx:Script>
</mx:Application>
According to this example, I order the array from highest to lowest and take the first. Its works perfectly. I hope this helps
Related
I'm completely new to Java Scipt although over the years I've messed around with VBA & Macros in Excel. I am now using Google Sheets almost exclusively, hence needing to learn Java.
I'm trying to jump to a specific cell (E5) if the current cell is (C14). This is what I've put together so far using scripts 'borrrowed' from others.
ie On entry of data in Cell C13 and pressing Enter, focus goes to Cell C14. The next data is to go into Cell E5.
function onSelectionChange(e) {
var sheetNames = ["Score Input"]; // Set the sheet name.
var ranges = ["C14"]; // Set the range to run the script.
var range = e.range;
var sheet = range.getSheet();
var check = ranges.some(r => {
var rng = sheet.getRange(r);
var rowStart = rng.getRow();
var rowEnd = rowStart + rng.getNumRows();
var colStart = rng.getColumn();
var colEnd = colStart + rng.getNumColumns();
return (range.rowStart >= rowStart && range.rowEnd < rowEnd && range.columnStart >= colStart && range.columnEnd < colEnd);
});
if (check) {
jumpToDetails();
}
};
function jumpToDetails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Score Input");
var goToRange = sheet.getRange('c14').getValue();
//sheet.getRange(goToRange).activate();
SpreadsheetApp.getActive().getRange('E5').activate();
}
It worked, or did until I inserted a row in the sheet, and even though I have changed the associated cell addresses, it now doesn't work?
Two questions. 'Why has it stopped working'? and 'Is there a simpler way to do it'?
I prefer using onEdit(e) on range C13 and jump to E5
For instance here is a script that jump from one cell to the following in addresses'list
function onEdit(event){
var sh = event.source.getActiveSheet();
var rng = event.source.getActiveRange();
if (sh.getName() == 'Score Input'){ // adapt
var addresses = ["C13","E5","E10","H10","E13","H13","E16"]; // adapt
var values = addresses.join().split(",");
var item = values.indexOf(rng.getA1Notation());
if (item < addresses.length - 1){
sh.setActiveSelection(addresses[item + 1]); // except last one
}
}
}
if you want to be able to add rows and columns, play with named ranges (for instance ranges names 'first', 'second, 'third')
function onEdit(event){
var sh = event.source.getActiveSheet();
var rng = event.source.getActiveRange();
if (sh.getName() == 'Score Input'){
var addresses = ["first","second","third"];
var values = addresses
.map(ad => myGetRangeByName(ad))
.join().split(",");
var item = values.indexOf(rng.getA1Notation());
if (item < addresses.length - 1){
sh.setActiveSelection(addresses[item + 1]); // except last one
}
}
}
function myGetRangeByName(n) {
return SpreadsheetApp.getActiveSpreadsheet().getRangeByName(n).getA1Notation();
}
reference
class NamedRange
I have a script that worked before, but for a few days, this one no longer works .....
I have an error:
"TypeError: function split not found in object 0. (line16, file" SplitAuto ")."
Can you help me please?
My script :
function splitAllTest(){
var ss=SpreadsheetApp.getActiveSpreadsheet();
var s=ss.getSheetByName("RĂ©ponses au formulaire 1");
var lr=s.getLastRow();
var lc=s.getLastColumn()-8; //data columns num
var range=s.getRange(1, 3, lr, lc).getValues()
var output=[];
var split=[];
var l = 0; // outout row count
for(var i=0;i<range.length;i++){ //row roop
// split column_data
var split = [];
var max1 = 0;
for(var j=0;j<range[0].length;j++){ // column roop
var colSplit = range[i][j].split(", ");
split[j] = colSplit;
if(max1 < split[j].length) max1 = split[j].length;
}
// push new rows data
for(var k=0;k<max1;k++){ // max1
output [l] = [];
for(var j=0;j<lc;j++){ // column
if(k < split[j].length) { // if length is 1 k is only 0
output[l].push(split[j][k]); // split [col_index][coldata_index]
}else{
//output[l].push(''); change 2017/03/08 takashi
output[l].push(j == 0 ? split[j][0]: ''); //only first name is filled on each associated line
}}
l++;
}}
ss.getSheetByName("Temp formulaire").clear().getRange(1, 2,
output.length,lc).setValues(output);
}
How to sort the items within each stacking column? Asc or desc.
Each series added to a chart is drawn on the chart in the order it was received. To change the order of the chart series you will need to change which series is the first in your list of series items.
That being said - what I think you want to do is to, independently of the series order, sort on each stack by value. I do not think this is possible in HighCharts.
You can only set global index of serie, but you cannot position each single "stack".
http://api.highcharts.com/highcharts#series.index
You may use the script below to sort the Stacked Chart Bars by category name.
var sortData = function(chartSource) {
var series = chartSource.series;
var axis = chartSource.xAxis[0];
var categories = [];
if($.isArray(series)) {
var ser =
$.grep(series, function(ser, seriesIndex)
{
return ser.visible;
})[0];
$.each(ser.data,
function(dataIndex, datum)
{
console.log(datum.category + ':' + datum.stackTotal);
var obj = {
name: datum.category,
index: dataIndex,
stackTotal: datum.stackTotal
}
categories.push(obj);
}
);
}
categories.sort(function(a, b) {
var aName = a.name.toLowerCase();
var bName = b.name.toLowerCase();
var aTotal = a.stackTotal;
var bTotal = b.stackTotal;
//if(aTotal === bTotal) {
return ((aName < bName) ? -1 : ((aName > bName) ? 1 : 0));
//} else {
// return ((aTotal > bTotal) ? -1 : ((aTotal < bTotal) ? 1 : 0));
//}
});
var mappedIndex = $.map(categories, function(category, index) {
return category.index;
});
categories = $.map(categories, function(category, index) {
return category.name;
});
console.log(categories);
console.log(mappedIndex);
axis.setCategories(categories);
var newDataArray = [];
$.each(series, function(seriesIndex, ser) {
newDataArray = [];
var data = $.map(mappedIndex, function(mappedIndex2, origIndex) {
var ydata = ser.data[mappedIndex2];
if(ydata.y!=null){
var y = ydata.y
newDataArray.push(y);
return y;
}
else
{
newDataArray.push(null);
return null;
}
});
ser.setData(newDataArray);
});
};
I have a number of objects arranged in a THREE.scene, and I want to calculate or retrieve a relative value indicating how much light each object is receiving from a single PointLight source. Simplified example:
With the light positioned at the camera, Block 1's value might be 0.50 since 3 of 6 faces are completely exposed, while 2 is ~0.33 and 3 is ~1.67.
I could probably do this the hard way by drawing a ray from the light toward the center of each face and looking at the intersects, but I'm assuming it's possible to directly retrieve the light level of each face.
This code takes the object's global matrix in consideration.
var amount = 0;
var rotationMatrix = new THREE.Matrix4();
var vector = new THREE.Vector3();
var centroid = new THREE.Vector3();
var normal = new THREE.Vector3();
for ( var i = 0; i < objects.length; i ++ ) {
var object = objects[ i ];
rotationMatrix.extractRotation( object.matrixWorld );
for ( var j = 0; j < object.geometry.faces.length; j ++ ) {
var face = object.geometry.faces[ j ];
centroid.copy( face.centroid );
object.matrixWorld.multiplyVector3( centroid );
normal.copy( face.normal );
rotationMatrix.multiplyVector3( normal );
vector.sub( light.position, centroid ).normalize();
if ( normal.dot( vector ) > 0 ) amount ++;
}
}
I think something like this should do the trick.
var amount = 0;
var faces = mesh.geometry.faces;
for ( var i = 0; i < geometry.faces.length; i ++ ) {
if ( geometry.faces[ i ].normal.dot( light.position ) > 0 ) amount ++;
}
(Warning: Brute force method!)
I'm including this for reference since it's what I'm currently using to meet all of the requirements described in the question. This function considers a face unlit if its center is not directly visible from the light's position.
I have no rotation matrix to consider for my application.
function getLightLevel(obj) {
/* Return percentage of obj.geometry faces exposed to light */
var litCount = 0;
var faces = obj.geometry.faces;
var faceCount = faces.length;
var direction = new THREE.Vector3();
var centroid = new THREE.Vector3();
for (var i=0; i < faceCount; i++) {
// Test only light-facing faces (from mrdoob's first answer).
if (faces[i].normal.dot(light.position) > 0) {
centroid.add(obj.position, faces[i].centroid);
direction.sub(centroid, light.position).normalize();
// Exclude face if centroid is obscured by another object.
var ray = new THREE.Ray(light.position, direction);
var intersects = ray.intersectObjects(objects);
if (intersects.length > 0 && intersects[0].face === faces[i]) {
litCount ++;
}
}
}
return litCount / faceCount;
}
I'm trying to distribute 3 objects randomly on my stage but it's not working. My movie is 800x800.
function makeRock():void{
var tempRock:MovieClip;
for(var i:Number = 1; i < 3; i++){
tempRock = new Rock();
tempRock.x = Math.round(800);
tempRock.y = Math.round(-800);
addChild(tempRock);
}
}
What am I doing wrong?
Replace Math.round(800); with Math.random()*800;
function makeRock():void
{
var tempRock:MovieClip;
var i:uint = 0;
for(i; i < 3; i++)
{
tempRock = new Rock();
tempRock.x = Math.random()*800;
tempRock.y = Math.random()*800;
addChild(tempRock);
}
}
Math.round(800) is just returning 800.
Math.random() returns a random number between 0 and 1, which you can multiply by 800 to get a random result of 0-800. A good note to make is that Math.random() never actually returns 1.0. Just everything from 0 up to 1.
Further reading:
As a side note: this makes it simple to return a random element from an array; because you're never getting 1 you can cast the result of Math.random()*array.length to uint() and always be within the boundaries of the array length.
eg.
var ar:Array = [1,2,"hello",4,5,6,7,8,9,0];
var randomElement:Object = ar[uint(Math.random()*ar.length)];
trace(randomElement);