I want to have 9 entries (numbering 1 thru 9), 9 times.
And an average for each set of 9 entries (these "sets" should hide until a button opens them for viewing).
The "sets" should have the date, then average displayed (upon user picking that data, it should open to show the 9 entries of 9 times).
Also a progressive overall average "of averages" (that always displays in the top-right corner).
Hope you can help...
If you can break it down for me I'd be happy to provide whatever insight I possess.
Example:
1) I would normally create a drop down list numbering 1,2,3,4,5,6,7,8,9.
So the user could select the number they wanted to use.
2) This number would be saved in a list.
After 9 numbers are selected and saved into that "list", I want the list saved.
2 items need to mark the meaning of the list.
A) Average
B) Date
And call that 1 entry.
Sample of 9 number list:
Average,3,5,7,3,5,2,4,8,4,date
Where the average of this list is 1st data in the list, and date is last.
An average in top right corner of the app would always reflect the list's average (the calculation gets the 1st data, or average, and averages the 5 data sets below. Then updates top right corner number with NEW average.
Let's say I've entered data 5 different times, the running average of the 1st data (or average) would show in top right corner.
I can write the whole thing in vlisp, create the dialog and database fairly quick.
Then create a video of what I want if that helps...
I've figured out how to use an image as a background, and size it to my prefered orientation.
Then create a drop down list with the data I needed, and then figured out how to update a createtextedit with the results.
I also figured out how to have "text to speech" read the results...
I still want to create an sql database with the results, AND average the results (to be continuously displayed).
I very impressed with droid script!
Wow...
Easy peasy so far.
But now I'm getting over my head with the methods needed to complete my app.
Dan
If you can post the code you have a question about someone will point you in the right direction. (Or post the Lisp, I can figure out an equivalent.)
Looks like what I need, but not sure enough how to code this language to empliment it correctly.
The visable running average needs to read the "average" (or 1st data on each db entry) to display the average.
Each selection needs to compare the number with a conditional statement to give the responce.
Example:
A zero is selected...
"Wow! That sucks! Shurly you can do better than that!"
A five is selected...
"Now your starting to get somewhere! Come on, I know you can do better!"
A nine is selected...
"Wow! Way to go! They can't touch that!"
Or what ever I decide to use for each number.
1) I'm not sure how to read the db lines to average them.
2) I'm still unclear how to rotate my text after I used "landscape" as the orientation.
3) Placing the drop-down and 2 other texts in the exact position I want them is beyond me too.
I tweaked your code a bit (but tried to leave explanations why.)
/* Globally scoped objects (everything is an object)
are available everywhere, as opposed to
function-scope objects which are only available within
that function. */
//Empty array to hold number list.
var list = [];
//See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
//and: https://medium.freecodecamp.org/reduce-f47a7da511a9
function listAvg() { return list.reduce( function(total, amount, index, array) {
total += amount;
if( index === array.length-1) {
return total/array.length;
} else {
return total;
}
});}
//Layout objects scoped globally so they can be
// accessed by event handlers:
var txt1; //Displays the average, updated in spin_OnChange function.
var spin; //Updated in spin_OnChange
var img; //Useless placeholder right now, could be part of awesome image carousel tomorrow.
//Called when application is started.
function OnStart()
{
//app.SetOrientation( "Landscape" );
//Create a layout with objects vertically centered.
var lay = app.CreateLayout( "linear", "VCenter,FillXY" );
//Create a blank image.
img = app.CreateImage( null, 0.2, 0.2 );
lay.AddChild( img );
//Add layout to app.
app.AddLayout( lay );
//Create a text label and add it to layout.
txt1 = app.CreateText( "Average Here", 0.3,0.08 );
txt1.SetTextColor( "#ff0000" );
txt1.SetBackColor( "#f2eaea" );
txt1.SetTextSize( 12 );
lay.AddChild( txt1 );
//Create some text.
var txt = app.CreateText( "Average\nSystem", 0.8, 0.2, "Multiline");
txt.SetTextSize( 22 );
txt.SetTextColor( "#ff0000" );
lay.AddChild( txt );
//Create spinner.
spin = app.CreateSpinner( "Pick:,0,1,2,3,4,5,6,7,8,9" );
spin.SetTextColor( "#ff0000" );
spin.SetBackColor( "#f2eaea" );
spin.SetTextSize( 22 );
spin.SetOnTouch( spin_OnChange );
lay.AddChild( spin );
//Add layout to app.
app.AddLayout( lay );
}
//Called when user changes the selection.
function spin_OnChange( item )
{
//Convert selected item from string to integer,
// and insert it and end of list.
list.push( parseInt( item ));
//app.ShowPopup( "Set = " + item );
txt1.SetText( "Average = " + listAvg() );
//Speak the text at default pitch and speed.
var pitch = 1.0, speed = 1.0;
app.TextToSpeech( txt1.GetText(), pitch, speed );
////Not sure how to save each item into a list
////This shows the number saved in "SetList"
//app.ShowPopup( item );
//app.SaveNumber( "SetList", item );
/* Since the handler only activates when the item
changes (hence 'OnChange'), set spinner back to
the item you don't want selected. */
spin.SelectItem( "Pick:" );
}
return total/array.length; return Math.round(total/array.length);return Math.round(total/array.length*10)/10;return Math.floor(total/array.length*10)/10;
return 1*(total/array.length).toFixed(1);
toFixed() might work better because it takes an optional number of decimals.
return Math.round(total/array.length*10)/10;
becomes...
return (total/array.length).toString(1);
It doesn't average the database numbers yet, and seriously needs documentation, but I wanted your take on it.
/**
* Average-Sets-DS
* Displays the average of 1-9 numbers,
* pushing the set of 9 numbers to storage
* when a new set of 9 is entered.
*/
/* ToDo:
* 1. Test app across different events such as OnPause, OnResume.
* 2. Write undo feature.
* 3. Write method to persist data to storage.
*/
// Displays the average of 9 numbers.
var numbersAverage = createText();
// Displays the average of averages.
var databaseAverage = createText();
// Doohicky to visually signify how many left to go.
var progressMeter = createProgressMeter();
// Displays numbers entered.
var numbersEntered = app.CreateText( "", 0.8 );
// Counts numbers in set.
var counter = 0;
// Array (set) of 9 numbers.
var numbersList = [];
// Array (set) of number lists, along with date and average.
var dataSets = [];
/*
Uses Array.reduce() method to sum all the elements
in an array, but on the last element divide the sum by
the length of the array.
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
and: https://medium.freecodecamp.org/reduce-f47a7da511a9
*/
function average( numbersArray ) { return numbersArray.reduce( function(total, amount, index, array) {
total += amount;
if( index === array.length-1) {
return (total/array.length).toFixed(1);
} else {
return total;
}
});}
/*
'app.Create*()' functions wrapped to create a single
location to adjust look and behavior; changing the look
of the wrapped button changes the look of all of
them. Returns control object.
*/
function createButton( text ) {
var button = app.CreateButton( text, 0.3, 0.1, "FontAwesome, Custom" );
button.SetStyle( "#0099cc","#33b5e5",20);
button.SetOnTouch( OnTouch );
return button;
}
/* Wired to variable to allow updating. */
function createText() {
var text = app.CreateText( "", 0.2 );
text.SetTextSize( 22 );
return text;
}
/* 'Throw-away' texts used as labels. */
function createLabel( text ) {
var label = app.CreateText( text )
label.SetTextSize( 20 );
return label;
}
/* Places an array of controls onto a horizontal layout. */
function createRow( controls ) {
var row = app.CreateLayout( "Linear", "Horizontal,FillX" );
controls.forEach( function( control ) { row.AddChild( control ) } );
return row;
}
/*
'Throw-away' texts used as vertical spacers.
Setting margins on all the controls would achieve
the same thing, but this was easier for the purpose
its used for.
*/
function createSpacer( height ) {
var spacer = app.CreateText( "", -1, height );
return spacer;
}
/*
Although the SeekBar is a user interface control, we
can use it as a progress display by using its SetValue
method, and prevent it from causing side effects by
not setting its SetOnClick method.
*/
function createProgressMeter() {
var meter = app.CreateSeekBar( 0.8 );
meter.IsEnabled( false );
meter.SetRange( 0.9 );
meter.SetValue( 0.0 );
return meter;
}
/* Creates main display, returning it as a layout object. */
function mainDisplay() {
var background = app.CreateLayout( "Linear", "FillXY" );
background.AddChild( createSpacer( 0.1 ) );
background.AddChild( createRow([createLabel("Average of Numbers: "), numbersAverage]) )
background.AddChild( createSpacer( 0.04 ) );
background.AddChild( createRow([createLabel("Average of Database: "), databaseAverage]) )
background.AddChild( createSpacer( 0.1 ) );
background.AddChild( createRow([createButton("7"),createButton("8"),createButton("9")]) )
background.AddChild( createRow([createButton("4"),createButton("5"),createButton("6")]) )
background.AddChild( createRow([createButton("1"),createButton("2"),createButton("3")]) )
background.AddChild( createRow([createButton("0"),createButton("[fa-undo]")]) )
background.AddChild( createSpacer( 0.1 ) );
background.AddChild( progressMeter );
background.AddChild( numbersEntered );
return background;
}
/* Display buttons handler. */
function OnTouch()
{
// Get the button object last pressed
var button = app.GetLastButton();
// Get the text of the button...
var text = button.GetText();
// Test to see if "undo" button was pressed by checking the Unicode value for [fa-undo].
if ( text === "\uf0e2" ) {
app.ShowPopup( "Undo not working (yet)" );
}
else {
// ...and also convert it to a number (we're going to be using both.)
var number = parseInt( text );
// Check the counter (numbersList.length would also work here.)
if (counter < 9) {
// Numbers list not yet full, so...
// numbersList[numbersList.length] = number should also work.
numbersList.push( number );
// Add the number to the display of numbers, update the progress meter, and display the average.
numbersEntered.SetText( numbersEntered.GetText() + " " + text );
progressMeter.SetValue( counter / 10 );
numbersAverage.SetText( average( numbersList ).toString() )
}
else {
// Numbers list was full, so push it to dataset list
var dataSet = {
avg: parseFloat( numbersAverage.GetText() ),
numbers: numbersList,
date: new Date(),
// Override Object.valueOf() method so it returns avg instead of [object object].
valueOf: function() { return this.avg; }
};
dataSets.push( dataSet );
//databaseAverage.SetText( averageDatasets( dataSets ))
databaseAverage.SetText( average( dataSets ))
//app.ShowPopup(JSON.stringify(averageDatasets( dataSets )))
numbersList = [ number ]
numbersEntered.SetText( text );
progressMeter.SetValue( 1 );
counter = 0;
}
counter++;
}
}
/* Back button handler. */
function OnBack() {
var dialog = app.CreateYesNoDialog( "Really quit?" )
dialog.SetOnTouch( OnDialog );
dialog.Show()
}
/* Quit dialog handler. */
function OnDialog( result ) {
if (result === "Yes") {
app.Exit();
}
}
//Called when application is started.
// This is the main routine so put settings that affect entire app here.
function OnStart()
{
app.EnableBackKey( false );
app.AddLayout( mainDisplay() );
}
function createSpacer( height ) {
var spacer = app.CreateText( "", -1, height );
return spacer;
}
In JavaScript any parameter you leave out when you call a function gets passed as "undefined" instead of throwing an error. So I told it "Create a blank text, make it the correct width for the text, use the height passed in, and to heck with the options."
To add to and remove from arrays, take a look at the JavaScript documentation for
Pop, Push, Shift and Unshift
For "Linear" layouts, to adjust spacing use:
SetPadding( left, top, right, bottom )
SetMargins( left, top, right, bottom )
Rarely used (because of taking into account all screen sizes might be different) the other option for placing controls is the "Absolute" layout:
SetPosition( left, top, width, height )
SetSize( width, height )
Also worth mentioning are the app methods:
GetDisplayWidth, GetScreenHeight, GetDisplayHeight, GetScreenHeight, and GetScreenDensity if you REALLY want to get technical about object placement. :-)
{ "time" : 32523353, "msg" : "App started", "count" : 4 },
{ "time" : 32523399, "msg" : "App connected", "count" : 3 },
{ "time" : .... etc
var s = app.ReadFile( "/sdcard/log.txt" );
var log = JSON.parse( "[" + s + "]" );
for( var i=0; i<log.length; i++ )
{
console.log( log[i].msg + " " + log[i].count );
}You will get a plain text file anyway.
I usually use .json for self-documenting.
icn=app.CreateText('[fa-bars] [fa-paste]',-1,-1,'fontawesome');
lay.AddChild(icn);
You may find it useful to post code you have tried and explain what you are not happy about with the result.